洛谷P1541

题目背景

小明过生日的时候,爸爸送给他一副乌龟棋当作礼物。

题目描述

乌龟棋的棋盘是一行 NN 个格子,每个格子上一个分数(非负整数)。棋盘第1格是唯一的起点,第 NN 格是终点,游戏要求玩家控制一个乌龟棋子从起点出发走到终点。

乌龟棋中 MM 张爬行卡片,分成4种不同的类型( MM 张卡片中不一定包含所有 44 种类型的卡片,见样例),每种类型的卡片上分别标有 1,2,3,41,2,3,4 四个数字之一,表示使用这种卡片后,乌龟棋子将向前爬行相应的格子数。游戏中,玩家每次需要从所有的爬行卡片中选择一张之前没有使用过的爬行卡片,控制乌龟棋子前进相应的格子数,每张卡片只能使用一次。

游戏中,乌龟棋子自动获得起点格子的分数,并且在后续的爬行中每到达一个格子,就得到该格子相应的分数。玩家最终游戏得分就是乌龟棋子从起点到终点过程中到过的所有格子的分数总和。

很明显,用不同的爬行卡片使用顺序会使得最终游戏的得分不同,小明想要找到一种卡片使用顺序使得最终游戏得分最多。

现在,告诉你棋盘上每个格子的分数和所有的爬行卡片,你能告诉小明,他最多能得到多少分吗?

输入输出格式

输入格式:

每行中两个数之间用一个空格隔开。

第 11 行 22 个正整数 N,MN,M ,分别表示棋盘格子数和爬行卡片数。

第 22 行 NN 个非负整数, a_1,a_2,…,a_Na1​,a2​,…,aN​ ,其中 a_iai​ 表示棋盘第 ii 个格子上的分数。

第 33 行 MM 个整数, b_1,b_2,…,b_Mb1​,b2​,…,bM​ ,表示M张爬行卡片上的数字。

输入数据保证到达终点时刚好用光 MM 张爬行卡片。

输出格式:

11 个整数,表示小明最多能得到的分数。

输入输出样例

输入样例#1: 复制

9 5
6 10 14 2 8 8 18 5 17
1 3 1 2 1

输出样例#1: 复制

73

说明

每个测试点 1s1s

小明使用爬行卡片顺序为 1,1,3,1,21,1,3,1,2 ,得到的分数为 6+10+14+8+18+17=736+10+14+8+18+17=73 。注意,由于起点是 11,所以自动获得第 11 格的分数 66 。

对于 30\%30% 的数据有 1≤N≤30,1≤M≤121≤N≤30,1≤M≤12 。

对于 50\%50% 的数据有 1≤N≤120,1≤M≤501≤N≤120,1≤M≤50 ,且 44 种爬行卡片,每种卡片的张数不会超过 2020 。

对于 100\%100% 的数据有 1≤N≤350,1≤M≤1201≤N≤350,1≤M≤120 ,且 44 种爬行卡片,每种卡片的张数不会超过 4040 ; 0≤a_i≤100,1≤i≤N,1≤b_i≤4,1≤i≤M0≤ai​≤100,1≤i≤N,1≤bi​≤4,1≤i≤M 。

看完题就想到了多重背包,有它的思想,但是不同的是题中给了路径,每一步必须记忆当前走到哪了,它会影响到下面的走法

所以又不是多重背包,不过也需要枚举所有卡片的数量

建立四维判断,每一维度是不同的卡片,dp值为当前取得的卡片总值

状态转移方程详见代码

#include <bits/stdc++.h>
using namespace std;
const int N = 360;
const int M = 45;
int n, m;
int a[N],b[5],dp[M][M][M][M];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);

    cin >> n >> m;
    for(int i = 1;i <= n;i ++)
        cin >> a[i];
    int t;
    for(int i = 1;i <= m;i ++)
        cin >> t, b[t] ++;

    dp[0][0][0][0] = a[1];

    for(int i = 0;i <= b[1];i ++)
    {
        for(int j = 0;j <= b[2];j ++)
        {
            for(int k = 0;k <= b[3];k ++)
            {
                for(int l = 0;l <= b[4];l ++)
                {
                    int g = 1 + i + 2 * j + 3 * k + 4 * l;

                    if(i) dp[i][j][k][l] = max(dp[i][j][k][l], dp[i-1][j][k][l] + a[g]);
                    if(j) dp[i][j][k][l] = max(dp[i][j][k][l], dp[i][j-1][k][l] + a[g]);
                    if(k) dp[i][j][k][l] = max(dp[i][j][k][l], dp[i][j][k-1][l] + a[g]);
                    if(l) dp[i][j][k][l] = max(dp[i][j][k][l], dp[i][j][k][l-1] + a[g]);
                }
            }
        }
    }

    cout << dp[b[1]][b[2]][b[3]][b[4]] << endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/soul_97/article/details/81320935