题目描述
小明过生日的时候,爸爸送给他一副乌龟棋当作礼物。
乌龟棋的棋盘只有一行,该行有 N 个格子,每个格子上一个分数(非负整数)。
棋盘第 1 格是唯一的起点,第 N 格是终点,游戏要求玩家控制一个乌龟棋子从起点出发走到终点。
乌龟棋中共有 M 张爬行卡片,分成 4 种不同的类型(M 张卡片中不一定包含所有 4 种类型的卡片),每种类型的卡片上分别标有1、2、3、4 四个数字之一,表示使用这种卡片后,乌龟棋子将向前爬行相应的格子数。
游戏中,玩家每次需要从所有的爬行卡片中选择一张之前没有使用过的爬行卡片,控制乌龟棋子前进相应的格子数,每张卡片只能使用一次。
游戏中,乌龟棋子自动获得起点格子的分数,并且在后续的爬行中每到达一个格子,就得到该格子相应的分数。
玩家最终游戏得分就是乌龟棋子从起点到终点过程中到过的所有格子的分数总和。
很明显,用不同的爬行卡片使用顺序会使得最终游戏的得分不同,小明想要找到一种卡片使用顺序使得最终游戏得分最多。
现在,告诉你棋盘上每个格子的分数和所有的爬行卡片,你能告诉小明,他最多能得到多少分吗?
输入格式
输入文件的每行中两个数之间用一个空格隔开。
第 1 行 2 个正整数 N 和 M,分别表示棋盘格子数和爬行卡片数。
第 2 行 N 个非负整数,$a_1$,$a_2$,……,$a_N$,其中 $a_i$ 表示棋盘第 i 个格子上的分数。
第 3 行 M 个整数,$b_1$,$b_2$,……,$b_M$,表示 M 张爬行卡片上的数字。
输入数据保证到达终点时刚好用光 M 张爬行卡片。
输出格式
输出只有 1 行,包含 1 个整数,表示小明最多能得到的分数。
样例
输入样例
9 5
6 10 14 2 8 8 18 5 17
1 3 1 2 1
输出样例
73
算法1
(线性DP) $O(n^4)$
观看题面,简化一下题面就是有一个数轴,现在给你一堆卡牌,每张卡牌对应你可以走的步数,也就是1,2,3,4。数轴上的每个点也分别有一些分数,问最多能得到多少分。
那么可以根据题意,然后设定一个f[i][j][k][l]数组,每张牌分别用i,j,k,l张能得到的最大分数,因为每张牌只能用一次,所以用哪张牌就直接从上一次转移过来就行。直接DP即可。
参考文献
敬请观看y总题解
C++ 代码
#include<bits/stdc++.h>
using namespace std;
int f[51][51][51][51];
int a[10000010];
int c[10000010];
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=m;i++)
{
int x;
cin>>x;
c[x]++;
}
f[0][0][0][0]=a[1];
for(int i=0;i<=c[1];i++)
{
for(int j=0;j<=c[2];j++)
{
for(int k=0;k<=c[3];k++)
{
for(int l=0;l<=c[4];l++)
{
if(i)
f[i][j][k][l]=max(f[i][j][k][l],f[i-1][j][k][l]+a[1+i+j*2+k*3+l*4]);
if(j)
f[i][j][k][l]=max(f[i][j][k][l],f[i][j-1][k][l]+a[1+i+j*2+k*3+l*4]);
if(k)
f[i][j][k][l]=max(f[i][j][k][l],f[i][j][k-1][l]+a[1+i+j*2+k*3+l*4]);
if(l)
f[i][j][k][l]=max(f[i][j][k][l],f[i][j][k][l-1]+a[1+i+j*2+k*3+l*4]);
}
}
}
}
cout<<f[c[1]][c[2]][c[3]][c[4]];
}