noip2003数字游戏
刚开始看到这个题的时候,感觉自己的DP转移方程写的是对的,但是还是差了一点,无论是dp还是搜索,状态的定义真的非常重要,此题是一个经典的区间DP的题,按照区间dp的一般思路写就好
k在i和j之间,所以k是>=i,<j的,这个一定要记清楚,同时dp的顺序也应该明白,先循环长度,然后循环i、j和k
此题还有一个重要的坑,如果对一个负数取模的话,一定要加上一个相当大的数,使其变成正数就好,刚开始wa掉的时候就因为这个原因,改过来居然对了
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; const int maxn=52; const int maxm=11; int n,m,a[maxn<<1+4],fx[maxn][maxn][maxm],fm[maxn][maxn][maxm],sum[maxn<<1+4]; int main() { //freopen("numgame.in","r",stdin); //freopen("numgame.out","w",stdout); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); sum[i]=sum[i-1]+a[i]; } for(int i=1;i<=n;i++) { a[i+n]=a[i]; sum[i+n]=sum[n]+sum[i]; } for(int i=1;i<=n;i++) for(int j=i;j<=i+n-1;j++) { fx[i][j][1]=(sum[j]-sum[i-1]+10000000)%10; fm[i][j][1]=(sum[j]-sum[i-1]+10000000)%10; } for(int k=2;k<=m;k++) { for(int i=1;i<=n;i++) for(int j=i+1;j<=i+n-1;j++) { fx[i][j][k]=0; fm[i][j][k]=0x3f3f3f3f; for(int x=i;x<j;x++)//x的范围应该是大于i小于j的 { fx[i][j][k]=max(fx[i][j][k],fx[i][x][k-1]*(((sum[j]-sum[x])+10000000)%10)); fm[i][j][k]=min(fm[i][j][k],fm[i][x][k-1]*(((sum[j]-sum[x])+10000000)%10)); } } } int mn=0x3f3f3f3f,mx=0; //最后的打擂台阶段 for(int i=1;i<=n;i++) { mx=max(mx,fx[i][i+n-1][m]); mn=min(mn,fm[i][i+n-1][m]); } printf("%d\n%d",mn,mx); } /** 10 3 -5864 1182 2731 2130 2737 -4613 9682 -3990 5327 2090 **/

浙公网安备 33010602011771号