其他分享
首页 > 其他分享> > 洛谷 P1541 乌龟棋

洛谷 P1541 乌龟棋

作者:互联网

P1541 [NOIP2010 提高组] 乌龟棋

题目背景

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

题目描述

乌龟棋的棋盘是一行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,状态表示有很多维~

首先想想这个题状态怎么表示,既然只有四种牌,并且每种牌不会超过40,可以开一个四维的数组来表示状态,具体表示为,每种牌已经使用的个数f(a,b,c,d)

想要找到的状态属性是最大值,所以每次状态转移时记得取个max

状态转移:将1,2,3,4其中一个牌用掉一张,并且获取在下一步将要获得的分数

假如用掉的是牌1,则f = max(f, f[a - 1][b][c][d] + score[...]) 这里f[a - 1][...]是上一个状态,也就是转移前的"未曾使用第一张牌"这个状态

题解:

/*
************************************
***********emu^w^***********
 
*/

#include <bits/stdc++.h>
using namespace std;
#define x first
#define y second
const int P = 13131;
#define ll long long
const int mod = 1E6 + 7;
const int INF = 0x3f, sINF = 0x3f3f3f3f;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef pair<long long, long long> PLL;
int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
//
const int N = 41;
int f[N][N][N][N];
int card[5], q[400];
int n, m;

int main()
{
    cin>>n>>m;
    for(int i = 0; i < n; i++) cin>>q[i];
    
    while(m--)
    {
        int temp;
        cin>>temp;
        card[temp]++;
    }
    
    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++)
                {
                    int temp = q[a + 2 * b + 3 * c + 4 * d];
                    int &v = f[a][b][c][d];
                    v = temp;
                    if(a) v = max(v, f[a - 1][b][c][d] + temp);
                    if(b) v = max(v, f[a][b - 1][c][d] + temp);
                    if(c) v = max(v, f[a][b][c - 1][d] + temp);
                    if(d) v = max(v, f[a][b][c][d - 1] + temp);
                }
                
        cout<<f[card[1]][card[2]][card[3]][card[4]];
}

时间复杂度O(40^4);

附带一张闫氏dp分析线性dp思维图

 

 

标签:分数,洛谷,格子,卡片,int,爬行,P1541,乌龟
来源: https://www.cnblogs.com/lviy/p/15651703.html