zstu 2555 数字游戏

总体上似乎做了2天。。
环状的话,首先想到枚举起点。。
枚举一圈就够了,于是有了math[i+n]=math[i]来满足这一点

然后想到了
dp[切成几份m][开始start][结束fin]=max(dp[先切k][start][切到i]*dp[再切k-m][i+1][fin])
每个保存的都是最优解。。

要满足这个,dp一开储存超多的数据,没有好的办法算出那么多数据比如:n个在一起的数据,这样铁定超时。。
想到n个在一起。。于是就想到了sum,用sum相减来求n个在一起。。

于是想到
dp[切成几份m][开始start][结束fin]=max(dp[先切k][start][切到i]*f(sum[fin]-sum[i+1]))…f是f(x)运算的意思。。
然后发现没办法使后半段切成多份。。
那么就把后半段当做整体吧。。

于是想到
dp[切成几份m][开始start][结束fin]=max(dp[先切m-1][开始start][切到i]*f(sum[fin]-sum[i+1]));

然后发现start这块可以没有。。在每次结束前判断一下是不是最大最小即可。。因为start就是枚举的起点。。在枚举后一直不变。。

#include<stdio.h>
#include<string.h>
int math[110];
int dpmax[10][55];
int dpmin[10][55];
int sum[55];
int max(int g,int h)
{
    return g>h?g:h;
}
int min(int g,int h)
{
    return g<h?g:h;
}
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&math[i]);
            math[i+n]=math[i];
        }
        int ansmin=0x3f3f3f3f;
        int ansmax=-1;
        int cin;
        for(int i=1;i<=n;i++)
        {
            cin=1;
            memset(sum,0,sizeof(sum));
            memset(dpmax,-1,sizeof(dpmax));
            memset(dpmin,0x3f3f3f3f,sizeof(dpmin));
            for(int j=i;j<=i+n-1;j++)
            {
                sum[cin]=sum[cin-1]+math[j];
                dpmax[1][cin]=(sum[cin]%10+10)%10;
                dpmin[1][cin]=dpmax[1][cin];
                cin++;
            }
            for(int j=2;j<=m;j++)
            {
                for(int k=j;k<=n;k++)
                {
                    for(int t=j-1;t<k;t++)
                    {
                        dpmax[j][k]=max(dpmax[j][k],dpmax[j-1][t]*(((sum[k]-sum[t])%10+10)%10));
                        dpmin[j][k]=min(dpmin[j][k],dpmin[j-1][t]*(((sum[k]-sum[t])%10+10)%10));
                    }
                }
            }
            ansmax=max(ansmax,dpmax[m][n]);
            ansmin=min(ansmin,dpmin[m][n]);
        }
        printf("%d\n%d\n",ansmin,ansmax);

    }
    return 0;
}

你可能感兴趣的:(dp,zstu)