乌龟棋

乌龟棋

有一个(1 imes n)的网格图,每个格子上有一个数字,有一只乌龟从第一个格子出发,现在有四种卡片,分别表示使用后向前走1,2,3,4步,有(a,b,c,d)张,每次可以任意选择一张卡片使用,保证用完卡片后到达第n个格子,到达的格子取走它的数字,问取走的数字之和的最大值,(1 ≤ N≤ 350,1 ≤M≤ 120),且4 种爬行卡片,每种卡片的张数不会
超过40。

不难想到设出表现走到的格子,和剩余的各种卡片的张数的递推方程,但事实上,确定了卡片张数,即确定了到达的格子,于是没必要保存,因此设(f[i][j][k][l])表示每种卡片各用了i,j,k,l张的取走的最大数字和,于是有

[f[i][j][k][l]=max{f[i-1][j][k][l],f[i][j-1][k][l], ]

[f[i][j][k-1][l],f[i][j][k][l-1]} ]

边界:(f[0][0][0][0]=0),其余无线小

答案:(f[a][b][c][d])

以下代码使用的是顺转移的方式。

参考代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#define il inline
#define ri register
using namespace std;
int dp[41][41][41][41],
    a[351],h[5];
il int max(int,int);
int main(){
    int n,m,i,j,k,l;scanf("%d%d",&n,&m);
    for(i=0;i<n;++i)scanf("%d",&a[i]);
    while(m--)scanf("%d",&i),++h[i];
    memset(dp,-1,sizeof(dp)),dp[0][0][0][0]=a[0];
    for(i=0;i<=h[1];++i)
        for(j=0;j<=h[2];++j)
            for(k=0;k<=h[3];++k)
                for(l=0;l<=h[4];++l){
                    if(dp[i][j][k][l]<0)continue;
                    dp[i+1][j][k][l]=max(dp[i+1][j][k][l],dp[i][j][k][l]+a[i+j*2+k*3+l*4+1]);
                    dp[i][j+1][k][l]=max(dp[i][j+1][k][l],dp[i][j][k][l]+a[i+j*2+k*3+l*4+2]);
                    dp[i][j][k+1][l]=max(dp[i][j][k+1][l],dp[i][j][k][l]+a[i+j*2+k*3+l*4+3]);
                    dp[i][j][k][l+1]=max(dp[i][j][k][l+1],dp[i][j][k][l]+a[i+j*2+k*3+l*4+4]);
                }printf("%d",dp[h[1]][h[2]][h[3]][h[4]]);
    return 0;
}
il int max(int a,int b){
    return a>b?a:b;
}
原文地址:https://www.cnblogs.com/a1b3c7d9/p/10995739.html