洛谷-1541 乌龟棋

题目描述
乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数)。棋盘第1格是唯一的起点,第N格是终点,游戏要求玩家控制一个乌龟棋子从起点出发走到终点。
乌龟棋中M张爬行卡片,分成4种不同的类型(M张卡片中不一定包含所有4种类型的卡片,见样例),每种类型的卡片上分别标有1,2,3,4四个数字之一,表示使用这种卡片后,乌龟棋子将向前爬行相应的格子数。游戏中,玩家每次需要从所有的爬行卡片中选择一张之前没有使用过的爬行卡片,控制乌龟棋子前进相应的格子数,每张卡片只能使用一次。
游戏中,乌龟棋子自动获得起点格子的分数,并且在后续的爬行中每到达一个格子,就得到该格子相应的分数。玩家最终游戏得分就是乌龟棋子从起点到终点过程中到过的所有格子的分数总和。
很明显,用不同的爬行卡片使用顺序会使得最终游戏的得分不同,小明想要找到一种卡片使用顺序使得最终游戏得分最多。
现在,告诉你棋盘上每个格子的分数和所有的爬行卡片,你能告诉小明,他最多能得到多少分吗?
输入输出格式
输入格式:
每行中两个数之间用一个空格隔开。
第1行2个正整数N,M,分别表示棋盘格子数和爬行卡片数。
第2行N个非负整数,a1,a2,…,aN​,其中a表示棋盘第iii个格子上的分数。
第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

输出样例#1:
73

说明
每个测试点1s
对于100%的数据有1≤N≤350,1≤M≤120,且4种爬行卡片,每种卡片的张数不会超过40;0≤ai≤100,1≤i≤N,1≤bi≤4,1≤i≤M

解释:看到数据范围,就知道很简单的记忆化搜索,设dp[i][a][b][c]表示现在在i,4有a,3有b,2有c的最大值,直接搜就OK

#include<iostream>
#define N 355
#define M 41
using namespace std;
int dp[N][M][M][M]={0};
int H[5]={0};
int A[N]={0};
int n=0,m=0;
int dfs(int x,int a,int b,int c){
    int sum=0;
    if(dp[x][a][b][c]) return dp[x][a][b][c];
    if(a) sum=max(sum,dfs(x+4,a-1,b,c));
    if(b) sum=max(sum,dfs(x+3,a,b-1,c));
    if(c) sum=max(sum,dfs(x+2,a,b,c-1));
    if(n-x-4*a-3*b-2*c) sum=max(sum,dfs(x+1,a,b,c));
    return dp[x][a][b][c]=sum+A[x];
}
int main(){
    ios::sync_with_stdio(false);
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>A[i];
    for(int i=1,temp;i<=m;i++){
        cin>>temp;H[temp]++;
    }
    dp[n][0][0][0]=A[n];
    cout<<dfs(1,H[4],H[3],H[2])<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/mkopvec/article/details/92019520
今日推荐