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 
**/

 

posted @ 2017-09-22 17:34  xinyimama  阅读(441)  评论(0)    收藏  举报