dp——洛谷 P1541 乌龟棋 —— by hyl天梦
题目:(转自 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个整数,表示小明最多能得到的分数。
输入输出样例
- 9 5
- 6 10 14 2 8 8 18 5 17
- 1 3 1 2 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天梦的更多相关文章
- 洛谷 p1541乌龟棋
洛谷 p1541乌龟棋 题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行NN个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第NN格是终点,游戏 ...
- 洛谷P1541 乌龟棋(四维DP)
To 洛谷.1541 乌龟棋 题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第N格是终点,游 ...
- 洛谷P1541 乌龟棋 [2010NOIP提高组]
P1541 乌龟棋 题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第N格是终点,游戏要求玩家 ...
- codevs1068 乌龟棋==洛谷P1541 乌龟棋
P1541 乌龟棋 题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第N格是终点,游戏要求玩家 ...
- 洛谷 P1541 乌龟棋 Label:O(n^4)的dp
题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第N格是终点,游戏要求玩家控制一个乌龟棋子从起 ...
- [洛谷P1541] 乌龟棋
洛谷题目链接:乌龟棋 题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第N格是终点,游戏要求玩 ...
- [NOIP2010] 提高组 洛谷P1541 乌龟棋
题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第N格是终点,游戏要求玩家控制一个乌龟棋子从起 ...
- 洛谷 P1541 乌龟棋
题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第N格是终点,游戏要求玩家控制一个乌龟棋子从起 ...
- 洛谷 P1541 乌龟棋 —— DP
题目:https://www.luogu.org/problemnew/show/P1541 DP. 代码如下: #include<iostream> #include<cstdio ...
随机推荐
- js基础——基本包装类型
1.基本包装类型String var bz = new String("Li.Linda"); //引用类型(object) bz.name= bz.subst ...
- springboot+nginx+https+linux实现负载均衡加域名访问简单测试
把springboot项目打包成三个jar包,并指定端口为 14341,14342,14343 下载腾讯云免费ssl证书,解压后会出现如下图文件夹 把nginx文件夹下的 .crt 和 .key文件复 ...
- 【t056】智力问答(链表+计数排序做法)
Time Limit: 1 second Memory Limit: 128 MB [问题描述] 新年联欢会上,G.Sha负责组织智力问答节目.G.Sha建立了一个很大很大的超级题库,并衡量了每道题的 ...
- Command failed: git -c core.longpaths=true config --get remote.origin.url
「Unable to Connect to GitHub.com For Cloning」 Error: Command failed: git -c core.longpaths=true conf ...
- Linux 内核驱动支持什么设备
struct usb_device_id 结构提供了这个驱动支持的一个不同类型 USB 设备的列表. 这个 列表被 USB 核心用来决定给设备哪个驱动, 并且通过热插拔脚本来决定哪个驱动自动加载, 当 ...
- 这群程序员疯了!他们想成为IT界最会带货的男人
随着网红主播越来越火,通过直播带货种草的形式也成了今年双12的热点. 不过,网红主播带货早已见怪不怪,但你们见过程序员直播带货吗!? 近日,趁着阿里云双12年末采购节,阿里云邀请了一波程序员GG来为大 ...
- onCreate不加载布局
如果Activity重写的是 onCreate(@Nullable Bundle savedInstanceState, @Nullable PersistableBundle persistentS ...
- Python8_关于编码解码和utf-8
关于编码:ASCII码是早期的编码规范,只能表示128个字符.7位二进制数表示 扩展ASCII码,由于ASCII码不够用,ASCII表扩充到256个符号,不同的国家有不同的标准:8位二进制数 Unic ...
- python 找出字符串中出现次数最多的字母
# 请大家找出s=”aabbccddxxxxffff”中 出现次数最多的字母 # 第一种方法,字典方式: s="aabbccddxxxxffff" count ={} for i ...
- 第二阶段:2.商业需求文档MRD:5.MRD-Roadmap及规划
产品路线图可以用泳道图来实现.将之前做过的泳道图的角色换为阶段即可. 可以以月为单位.左边就是一些产品的功能. 基础功能,有的功能会跨月甚至夸功能模块.比如图中的会员等级. 通过线段来联系各个功能与先 ...