1541 乌龟棋
难度:普及+/提高
题目类型:动态规划
提交次数:2
涉及知识:多维动规
题目背景
小明过生日的时候,爸爸送给他一副乌龟棋当作礼物。
题目描述
乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数)。棋盘第1格是唯一的起点,第N格是终点,游戏要求玩家控制一个乌龟棋子从起点出发走到终点。
乌龟棋中M张爬行卡片,分成4种不同的类型(M张卡片中不一定包含所有4种类型的卡片,见样例),每种类型的卡片上分别标有1、2、3、4四个数字之一,表示使用这种卡片后,乌龟棋子将向前爬行相应的格子数。游戏中,玩家每次需要从所有的爬行卡片中选择一张之前没有使用过的爬行卡片,控制乌龟棋子前进相应的格子数,每张卡片只能使用一次。
游戏中,乌龟棋子自动获得起点格子的分数,并且在后续的爬行中每到达一个格子,就得到该格子相应的分数。玩家最终游戏得分就是乌龟棋子从起点到终点过程中到过的所有格子的分数总和。
很明显,用不同的爬行卡片使用顺序会使得最终游戏的得分不同,小明想要找到一种卡片使用顺序使得最终游戏得分最多。
现在,告诉你棋盘上每个格子的分数和所有的爬行卡片,你能告诉小明,他最多能得到多少分吗?
代码:
1 #include<iostream> 2 using namespace std; 3 int score[400]; 4 int card[4]; 5 int f[41][41][41][41]; 6 int n, m; 7 int ans; 8 int main(){ 9 cin>>n>>m; 10 int i, j, k, l; 11 for(i = 1; i <= n; i++) 12 cin>>score[i]; 13 for(i = 1; i <= m; i++){ 14 int num; 15 cin>>num; 16 card[num]++; 17 } 18 for(i = 0; i <= card[1]; i++) 19 for(j = 0; j <= card[2]; j++) 20 for(k = 0; k <= card[3]; k++) 21 for(l = 0; l <= card[4]; l++){ 22 int maxx = 0; 23 if(i!=0&&f[i-1][j][k][l]>maxx) 24 maxx = f[i-1][j][k][l]; 25 if(j!=0&&f[i][j-1][k][l]>maxx) 26 maxx = f[i][j-1][k][l]; 27 if(k!=0&&f[i][j][k-1][l]>maxx) 28 maxx = f[i][j][k-1][l]; 29 if(l!=0&&f[i][j][k][l-1]>maxx) 30 maxx = f[i][j][k][l-1]; 31 f[i][j][k][l] = maxx + score[1+i*1+j*2+k*3+l*4]; 32 } 33 cout<<f[card[1]][card[2]][card[3]][card[4]]; 34 return 0; 35 }
备注:
先写了一遍dfs,第一遍样例就过了,还觉得至少能骗一半分。。结果只过了一个点。
看了题解,听说这就是一个背包动规,大概就是多重背包吧。f[i][j][k][l]表示取了i张1卡,j张2卡,k张3卡和l张4卡时的最大分数,不难发现f[i][j][k][l]等于四种卡分别少拿一张时的最大值加上当前格的值。不用考虑顺序,可以理解,又似乎有点谜的。。