题目:
有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;
}