2010提高组-乌龟棋 [记忆优化搜索]

题目:
有n个格子,你有m张牌,每张牌上面有个数字,用了这张牌你就可以走这张牌上对应的数字了,每到达一个格子,你就会获得格子上相应的分数,问你如何合理的出牌,使分数最大化。

记忆优化搜索可能会好写一点

题解:
我们让他从0开始,dfs的四个元素,表示的是当前使用了多少个1,2,3,4号牌。

但是为什么我们计算的位置是a + b * 2 + c * 3 + d * 4 + 1,为什么要有个+1,原因很简单,是因为他是从1位置开始的,自动获取1位置上面的分数。

边界如何判断呢,当所有扑克牌用完以后也就是说到达边界了,当a+b+c+d==m时,即为到达边界。

代码:

/*Keep on going Never give up*/
#pragma GCC optimize(3,"Ofast","inline")
#include 
const int maxn = 1e6+10;
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
const int mod = 100000000;
using namespace std;
int dp[41][41][41][41];
int num[10];
int maps[500];
int imax=0;
int n,m;
int dfs(int a,int b,int c,int d){
    if(dp[a][b][c][d])   return dp[a][b][c][d];
    if(a+b+c+d==m) return 0;
    int steps=a+2*b+3*c+4*d+1;
    int imax=0;
    if(num[1]>a) imax=max(imax,dfs(a+1,b,c,d)+maps[steps+1]);
    if(num[2]>b) imax=max(imax,dfs(a,b+1,c,d)+maps[steps+2]);
    if(num[3]>c) imax=max(imax,dfs(a,b,c+1,d)+maps[steps+3]);
    if(num[4]>d) imax=max(imax,dfs(a,b,c,d+1)+maps[steps+4]);
    return dp[a][b][c][d]=imax;
}
int main() {
    cin>>n>>m;
    int t;
    for(int i=1;i>maps[i];
    for(int i=0;i<m;i++){
        cin>>t;
        num[t]++;
    }
    int x=dfs(0,0,0,0);
    printf("%d\n",x+maps[1]);
    return 0;
}

你可能感兴趣的:(牛客每日一题,题解)