题目:(转自 https://www.luogu.com.cn/problem/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,2

1,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≤b[i]≤4,1≤i≤M。

很明显,暴力dfs是一个不错的选择,如若是在考试,天梦在这里奉告读者结合实际情况打暴力。但由于是一道dp,我们今天就讲讲正解。

思路:

在做这道题时,我首先这样想:把起始点标注成s和t,在中间找一点i保证 f[s][i] 和 f[i][t] 最优,通过 f[i][j]=f[s][i]+f[i][t]这个式子来让f[s][t]最优,但可以很快证明这个想法是错误的,因为设我们能用的总牌数为K,

前一段(即f[s][i])为了得到最优解会用a张牌,后一段(即f[i][t])为了得到最优解会用b张牌,无法保证a+b=K。

除了枚举分段点,我们还能枚举什么? 用的牌数。接下来我来给大家做简单介绍。

介绍:

设f[i][j][p][k]表示用了i张走一步的牌(下面简写),j张2,p张3,k张4,则我们理想的最优解应该是他走到终点时,即所有牌都用完时。我们以样例为例:f【3】【1】【1】【0】为我们所求的最优解,因为上一步可能走了1格,2格,3格,4格(由于题目限制,4在样例中牌数为0)

那么最优解可以由f[2][1][1][0],f[3][0][1][0],f[3][1][0][0] 得到

一般的f[i][j][k][p]可以由f[i-1][j][k][p], f[i][j-1][k][p], f[i][j][k-1][p], f[i][j][k][p-1]得到,如果读者接着往上推(试试推推样例) 会发现最终的最优解都是由f[0][0][0][0]得到的,它的值是什么?一格都没走——起点值。

下面,让我们来看看代码:

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
#define N 400
#define ll long long
using namespace std;
int n,m;
int a[N];
int sum[];
int f[][][][];
int main()
{
cin>>n>>m;
for(int i=;i<=n;i++)
{
cin>>a[i];
}
for(int i=;i<=m;i++)
{
int x;
cin>>x;
sum[x]++;
}//计算牌数
//memset(f,0,sizeof(f));
f[][][][]=a[];
//cout<<sum[1]<<" "<<sum[2]<<" "<<sum[3]<<" "<<sum[4]<<endl<<endl;
for(int i=;i<=sum[];i++)
{
for(int j=;j<=sum[];j++)
{
for(int k=;k<=sum[];k++)
{
for(int p=;p<=sum[];p++)
{
if(!(i==&&j==&&k==&&p==))
{
int ans1,ans2,ans3,ans4;
if(i-<) ans1=; else ans1=f[i-][j][k][p];
if(j-<) ans2=; else ans2=f[i][j-][k][p];
if(k-<) ans3=; else ans3=f[i][j][k-][p];
if(p-<) ans4=; else ans4=f[i][j][k][p-];//防止数组下溢
f[i][j][k][p]=max(max(ans1,ans2),max(ans3,ans4))+a[i*+j*+k*+p*+];//加上这个位置的格子值,别忘了加1
}
}
}
}
}
cout<<f[sum[]][sum[]][sum[]][sum[]];
return ;
}

dp——洛谷 P1541 乌龟棋 —— by hyl天梦的更多相关文章

  1. 洛谷 p1541乌龟棋

    洛谷 p1541乌龟棋 题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行NN个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第NN格是终点,游戏 ...

  2. 洛谷P1541 乌龟棋(四维DP)

    To 洛谷.1541 乌龟棋 题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第N格是终点,游 ...

  3. 洛谷P1541 乌龟棋 [2010NOIP提高组]

    P1541 乌龟棋 题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第N格是终点,游戏要求玩家 ...

  4. codevs1068 乌龟棋==洛谷P1541 乌龟棋

    P1541 乌龟棋 题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第N格是终点,游戏要求玩家 ...

  5. 洛谷 P1541 乌龟棋 Label:O(n^4)的dp

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

  6. [洛谷P1541] 乌龟棋

    洛谷题目链接:乌龟棋 题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第N格是终点,游戏要求玩 ...

  7. [NOIP2010] 提高组 洛谷P1541 乌龟棋

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

  8. 洛谷 P1541 乌龟棋

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

  9. 洛谷 P1541 乌龟棋 —— DP

    题目:https://www.luogu.org/problemnew/show/P1541 DP. 代码如下: #include<iostream> #include<cstdio ...

随机推荐

  1. 154th LeetCode Weekly Contest

    A B D均比较简单.先说C题 K-Concatenation Maximum Sum Given an integer array arr and an integer k, modify the ...

  2. Mail.Ru Cup 2018 Round 2 B. Alice and Hairdresser (bitset<> or 其他)

    传送门 题意: 给出你序列 a,在序列 a 上执行两种操作: ① 0 :查询有多少连续的片段[L,...,R],满足 a[L,...,R] > l: ② 1 p d :将第 p 个数增加 d: ...

  3. H3C IP地址拒绝及释放

  4. 第3本:Visual Studio程序员箴言

    第3本:Visual Studio程序员箴言 Visual Studio 2010是我经常使用的程序开发工具,也知道VS中有大量的快捷键可以帮助提高效率,可惜就是不愿意记忆,最近在学vim的时候快速把 ...

  5. 【codeforces 749B】Parallelogram is Back

    time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard ou ...

  6. Linux 内核pci添加一个驱动

    一个 PCI 驱动被添加到 PCI 核心, 当它调用 pci_register_driver 函数时. 这个函数 只初始化 struct device_driver 结构, 这个结构包含在 struc ...

  7. LightOJ - 1284 Lights inside 3D Grid (概率计算)

    题面: You are given a 3D grid, which has dimensions X, Y and Z. Each of the X x Y x Z cells contains a ...

  8. dotnet 如何调试某个文件是哪个代码创建

    我发现了自己的软件,会在桌面创建一个 1.txt 文件,但是我不知道是哪个代码创建的,那么如何进行快速的调试找到是哪个代码创建的 最简单的方法是使用 VisualStudio 全局搜 1.txt 看是 ...

  9. dotnet 通过 WMI 获取系统安装的驱动

    本文告诉大家如何通过 WMI 获取用户已经安装的驱动程序 通过 Win32_SystemDriver 可以获取用户已经安装的驱动程序 var mc = "Win32_SystemDriver ...

  10. oracle解除被锁定的表的状态

      select b.owner,b.object_name,a.session_id,a.locked_mode,c.serial#,c.sid||','||c.serial# from v$loc ...