题目描述
解题思路
首先这是一个很明显的线性dp的题目,很容易发现规律
数据输入
我们用 h[ N ] 数组存储每一个格子的分数
用 cnt [ ],数组表示每一中卡片的数目
1,状态表示
因为这里一个有4种跳跃方式可以选择
f[ i ][ a ][ b ][ c ][ d ]表示 走到第 i 个格子的时候,1,2,3,4四种跳跃卡片分别用了,a,b,c,d张。
但是其实我们是可以去掉一维的,因为我们可以根据 1,2,3,4卡片的使用情况来推算我们当前到的位置 i = a + 2 * b + 3 * c + 4 * d
所以我们的状态表示为
f[ a ][ b ][ c ][ d ]表示 走到第 i = a + 2 * b + 3 * c + 4 * d 个格子的时候,1,2,3,4四种跳跃卡片分别用了,a,b,c,d张。
2,状态转移方程
f[ a ][ b ][ c ][ d ]
= max(f[ a - 1 ][ b ][ c ][ d ], f[ a ][ b - 1 ][ c ][ d ],f[ a ][ b ][ c - 1 ][ d ] ,f[ a ][ b ][ c ][ d - 1] ) + h[ j ]
3,初始化
根据题目信息 “游戏中,乌龟棋子自动获得起点格子的分数”
f[0][0][0][0] = h[0],因为价值大于等于 0 ,其他的格子都初始化为 0 即可。
4,填表顺序
咱们 4层for 从 a 到 d,从小到大即可
5,最终答案
f[ cnt[ 1 ] ] [ cnt[ 2 ] ] [ cnt[ 3 ] ] [ cnt[ 4 ] ]
6,AC代码
#include <iostream>
using namespace std;
const int M = 45;
const int N = 360;
int h[N] = { 0 };
int f[M][M][M][M] = { 0 };
int cnt[5] = { 0 };
int n, m, sum;
int main()
{
cin >> n >> m;
for (int i = 0; i < n; i++)
{
cin >> h[i];
}
for (int i = 1; i <= m; i++)
{
int x;
cin >> x;
cnt[x]++;
}
f[0][0][0][0] = h[0];
for (int a = 0; a <= cnt[1]; a++)
{
for (int b = 0; b <= cnt[2]; b++)
{
for (int c = 0; c <= cnt[3]; c++)
{
for (int d = 0; d <= cnt[4]; d++)
{
int j = a + b * 2 + c * 3 + d * 4;
if (a - 1 >= 0)
{
f[a][b][c][d] = max(f[a][b][c][d], f[a - 1][b][c][d] + h[j]);
}
if (b - 1 >= 0)
{
f[a][b][c][d] = max(f[a][b][c][d], f[a][b - 1][c][d] + h[j]);
}
if (c - 1 >= 0)
{
f[a][b][c][d] = max(f[a][b][c][d], f[a][b][c - 1][d] + h[j]);
}
if (d - 1 >= 0)
{
f[a][b][c][d] = max(f[a][b][c][d], f[a][b][c][d - 1] + h[j]);
}
}
}
}
}
cout << f[cnt[1]][cnt[2]][cnt[3]][cnt[4]] << endl;
return 0;
}