洛谷P1541 乌龟棋

题目背景

小明过生日的时候,爸爸送给他一副乌龟棋当作礼物。
乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数)。棋盘第1格是唯一的起点,第N格是终点,游戏要求玩家控制一个乌龟棋子从起点出发走到终点。

没有使用过的爬行卡片,控制乌龟棋子前进相应的格子数,每张卡片只能使用一次。游戏中,乌龟棋子自动获得起点格子的分数,并且在后续的爬行中每到达一个格子,就得到该格子相应的分数。玩家最终游戏得分就是乌龟棋子从起点到终点过程中到过的所有格子的分数总和。很明显,用不同的爬行卡片使用顺序会使得最终游戏的得分不同,小明想要找到一种卡片使用顺序使得最终游戏得分最多。
现在,告诉你棋盘上每个格子的分数和所有的爬行卡片,你能告诉小明,他最多能得到多少分吗?
输入
输入的每行中两个数之间用一个空格隔开。
第1行2个正整数N和M,分别表示棋盘格子数和爬行卡片数。
第2行N个非负整数,a1, a2,......, aN,其中ai表示棋盘第i个格子上的分数。
第3行M个整数,b1,b2,......, bM,表示M张爬行卡片上的数字。输入数据保证到达终点时刚好用光M张爬行卡片,即
输出
输出只有1行,1个整数,表示小明最多能得到的分数。
样例输入
9 5
6 10 14 2 8 8 18 5 17
1 3 1 2 1
样例输出
73
提示

【输入输出样例说明】
小明使用爬行卡片顺序为1,1,3,1,2,得到的分数为6+10+14+8+18+17=73。注意,由于起点是1,所以自动获得第1格的分数6。


我说这是DP没人反驳吧(暴力dalao退下)

就是类似于在额定步数内求能到达的值的最大值

现在给了一条标了值的数轴和四个变量,分别表示能走1-4步的次数

则一开始定义这些东西

1 int n,m;//点数和卡数
2 int point[351];//表示第几个点所表示的数值
3 int card[5]={0};//表示每种牌有几张
4 int dp[41][41][41][41]={0};//将初始时的点数初始化为0

然后就是DP(草,这么草率的吗

哦不我们先写一下输入

1 scanf("%d%d",&n,&m);
2 for(int i=1;i<=n;i++)
3      scanf("%d",&point[i]);
4      for(int i=1;i<=m;i++)
5 {
6             int x;
7             scanf("%d",&x);
8             card[x]++; 
9 }

现在我们有了n和m,以及一个表示每个点值的数组以及四个表示卡牌数量的数组

于是乎开始DP

而且很明显此时的值是冗余的,可以靠手牌分别消耗的多少算出

别问我怎么知道的(ZHX讲了)

则可以将数组从五维变成四维

降低复杂度

1 for(int a=0;a<=card[1];a++)
2 for(int b=0;b<=card[2];b++)
3 for(int c=0;c<=card[3];c++)
4 for(int d=0;d<=card[4];d++)
5 dp[a][b][c][d]=max(max(max(dp[max(0,a-1)][b][c][d],dp[a][max(0,b-1)][c][d]),dp[a][b][max(0,c-1)][d]),dp[a][b][c][max(0,d-1)])+point[1+a+2*b+3*c+4*d]

数组dp[a][b][c][d]表示的是在四张卡牌数量分别为abcd是所能得到的最大分数

想要求到它则需要四个不同到达方法(也就是从前一二三四个格子分别过来)

在这四种情况中选最优解

然后再寻找从1到n的最大值(因为)

AC代码如下

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<map>
#include<stack>
using namespace std;
int n,m;
int point[351];
int card[5]={0};
int dp[41][41][41][41]={0};
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&point[i]);
        for(int i=1;i<=m;i++)
        {
            int x;
            scanf("%d",&x);
            card[x]++; 
        }
        for(int a=0;a<=card[1];a++)
        for(int b=0;b<=card[2];b++)
        for(int c=0;c<=card[3];c++)
        for(int d=0;d<=card[4];d++)
        dp[a][b][c][d]=max(max(max(dp[max(0,a-1)][b][c][d],dp[a][max(0,b-1)][c][d]),dp[a][b][max(0,c-1)][d]),dp[a][b][c][max(0,d-1)])+point[1+a+2*b+3*c+4*d];
        printf("%d",dp[card[1]][card[2]][card[3]][card[4]]);
        return 0;
}

End

又水了一篇

原文地址:https://www.cnblogs.com/Jiangxingchen/p/12988986.html