乌龟棋(NOIP2010)

传送门
这道题在当年应该是一道中高档的题,如今,呵呵,只能算得上签到题了吧!
这显然是dp。
我们弄一个数组f[i][j][k][l],它表示当我们用i张1,j张2,k张3,l张4的卡片时,我们得到的最大分数。
怎么想到的?
这里写图片描述
你把页面翻到最小面,你就会看见这两行字,没错,这绝对是暗示。
那这样有什么好处?
我们可以快速定位当前到了哪一个格子,因为我们已经知道用了哪些卡片。
而且我们知道这样可以避免因为卡片顺序带来的错误。
代码如下(转移方程自己看):

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m;
int score[355];
int vis[10];
int z;
int f[45][45][45][45];
int res;
int main(){
    res=-1;
    memset(vis,0,sizeof(vis));
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d",&score[i]);
    }
    for(int i=0;i<m;i++){
        scanf("%d",&z);
        vis[z]++;
    }
    memset(f,-1,sizeof(f));
    f[0][0][0][0]=score[1];
    for(int i=0;i<=vis[1];i++){
        for(int j=0;j<=vis[2];j++){
            for(int k=0;k<=vis[3];k++){
                for(int l=0;l<=vis[4];l++){
                    int now=i+2*j+3*k+4*l+1;
                    if(now<=n){
                        int& ans=f[i][j][k][l];
                        if(i>0&&f[i-1][j][k][l]>=0){
                            ans=max(ans,f[i-1][j][k][l]+score[now]);
                        }
                        if(j>0&&f[i][j-1][k][l]>=0){
                            ans=max(ans,f[i][j-1][k][l]+score[now]);
                        }
                        if(k>0&&f[i][j][k-1][l]>=0){
                            ans=max(ans,f[i][j][k-1][l]+score[now]);
                        }
                        if(l>0&&f[i][j][k][l-1]>=0){
                            ans=max(ans,f[i][j][k][l-1]+score[now]);
                        }
                        res=max(res,ans);
                    }

                }
            }
        }
    }
    printf("%d",res);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/cggwz/article/details/81675530