【AcWing】蓝桥杯集训每日一题Day20|线性DP|312.乌龟棋(C++)

312.乌龟棋
312. 乌龟棋 - AcWing题库
难度:简单
时/空限制:1s / 64MB
总通过数:5184
总尝试数:8091
来源: 《算法竞赛进阶指南》NOIP2010提高组
算法标签 DP线性DP

题目内容

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

乌龟棋的棋盘只有一行,该行有 N 个格子,每个格子上一个分数(非负整数)。

棋盘第 1 格是唯一的起点,第 N 格是终点,游戏要求玩家控制一个乌龟棋子从起点出发走到终点。

乌龟棋中共有 M 张爬行卡片,分成 4 种不同的类型(M 张卡片中不一定包含所有 4 种类型的卡片),每种类型的卡片上分别标有 1、2、3、4 四个数字之一,表示使用这种卡片后,乌龟棋子将向前爬行相应的格子数。

游戏中,玩家每次需要从所有的爬行卡片中选择一张之前没有使用过的爬行卡片,控制乌龟棋子前进相应的格子数,每张卡片只能使用一次。

游戏中,乌龟棋子自动获得起点格子的分数,并且在后续的爬行中每到达一个格子,就得到该格子相应的分数。

玩家最终游戏得分就是乌龟棋子从起点到终点过程中到过的所有格子的分数总和。

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

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

输入格式

输入文件的每行中两个数之间用一个空格隔开。

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

第 2 行 N 个非负整数,a1,a2,......,aN,其中 ai 表示棋盘第 i 个格子上的分数。

第 3 行 M 个整数,b1,b2,......,bM,表示 M 张爬行卡片上的数字。

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

输出格式

输出只有 1 行,包含 1 个整数,表示小明最多能得到的分数。

数据范围

1≤N≤350,

1≤M≤120,

0≤ai≤100,

1≤bi≤4,

每种爬行卡片的张数不会超过 40。

输入样例:

复制代码
9 5
6 10 14 2 8 8 18 5 17
1 3 1 2 1
输出样例:
复制代码
73
题目解析

保证所有卡片用光的时候,刚好可以从1号格子跳到n号格子

使用的顺序可以任意取

每一个格子上有一个非负整数的分数

每走到一个格子,就可以把格子上的分数加起来

在所有跳的方案当中,总分的最大值是多少

总长度最大是350,总卡片数最多是120,每一种卡片最多40张

因为方案数非常多,所以用DP,而不是暴搜

  1. 直观定义状态的时候,肯定n有一维,四种卡片有多少张,各有一维

    f[i][A][B][C][D]

这样一定会爆空间和时间

  1. 其实可以去掉一维,D可以计算
    f[i][A][B][C]D =(i - 1 - A - 2B - 3C)/4

    不过也很大,会超内存

  2. 这五维不是互相独立的,去掉D可以,去掉n也是可以的,因为n可以被算出来
    n = 1 + A + 2B + 3C + 4D

    状态数是41的4次方,可以接受

DP
状态表示

f[A][B][C][D]

  1. 表示哪个集合
    所有编号为1,2,3,4的卡分别使用了A,B,C,D张的方案的集合
  2. 存的是哪个属性
    每一个方案的分值的最大值

每个状态怎么算出来

对应的是集合的划分

要求集合中所有方案的最大值的话,一般是将这个集合划分成若干个子集,划分的时候一般是找最后一个不同点

1,2,3,4各使用A,B,C,D张的话,最后一张可以用1234中的任意一种,所以可以分成4大类,这样的方式可以将方案不重不漏的分为4类。

每种方案最后只能用1种数字,一定是没有重复的,任意两个子集之间一定是没有交集的,任意一个方案一定使用过最后一张,每一种方案一定是属于某一个子集的

如何求当前集合的最大值

只要分别求一下每一个子集的最大值,在整体取一个max,就得到整个集合的最大值了

  1. 每一个子集的最大值怎么求
    求第一个子集的最大值,从定义出发
  • 第一个子集表示从1号格子使用了A张1,B张2,C张3,D张4,使用完之后,跳到了某个格子,最后使用的是1,也就是最后一次跳了1步,的所有方案的集合
    最后一次用的是1,前面就是A-1张1,B张2,C张3,D张4
  • 第二个子集同上
    最后一次用的是2,前面就是A张1,B-1张2,C张3,D张4
  • 其余子集同理
  1. 每一类怎么求最大值
    前面的方案数是很多的,最后一步都一样,都是从某个格子跳到最后一个格子,最后一步的分值都是score
    对于第一类来说,最后一步的分值都一样,如果想求整个方案的最大值的话,应该让前面变化的部分取最大值

前面变化的部分,所有1234分别使用A-1,B,C,D张的所有方案的集合,要从这个集合当中取一个最大值,根据状态描述,恰好就是f[A-1][B][C][D]

加上最后一个格子的分值,就是第一类的最大值
f A − 1 B C D + s c o r e fA-1BCD+score fA−1BCD+score

同理第二类
f A B − 1 C D + s c o r e fAB-1CD+score fAB−1CD+score

第三类
f A B C − 1 D + s c o r e fABC-1D+score fABC−1D+score

第四类
f A B C D − 1 + s c o r e fABCD-1+score fABCD−1+score

f[A][B][C][D]的最大值等于这四种情况取max

代码
复制代码
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 360, M = 41;

int n, m;
//w表示每个格子的分值,s表示1234的数量
int w[N], s[N];
int f[M][M][M][M];   //f是状态数组

int main()
{
	scanf("%d%d", &n, &m);
	//先读入每个格子的分值
	for (int i = 1; i <= n; i ++) scanf("%d", &w[i]);

	//读入m张卡片
	while (m --)
	{
		int x;
		scanf("%d", &x);
		s[x] ++;
	}

	//设置初值,一开始在起点,分值是1
	f[0][0][0][0] = w[1];
	//枚举一下所有状态
	for (int A = 0; A <= s[1]; A ++)
		for (int B = 0; B <= s[2]; B ++)
			for (int C = 0; C <= s[3]; C ++)
				for (int D = 0; D <= s[4]; D ++)
				{
					//先存跳到格子的分值
					int score = w[1 + A + B * 2 + C * 3 + D * 4];
					//把当前状态存下来
					int& v = f[A][B][C][D];
					//如果A是有的话,最后一张可以用A
					if (A) v = max(v, f[A-1][B][C][D] + score);
					if (B) v = max(v, f[A][B-1][C][D] + score);
					if (C) v = max(v, f[A][B][C-1][D] + score);
					if (D) v = max(v, f[A][B][C][D-1] + score);
				}
	printf("%d\n", f[s[1]][s[2]][s[3]][s[4]]);
	return 0;
}
相关推荐
混迹中的咸鱼4 分钟前
游戏开发核心架构指南
c++·游戏·架构
-凌凌漆-15 分钟前
【Qt】C++中protected与private的区别
开发语言·c++·qt
草莓熊Lotso22 分钟前
【Linux网络】深入理解 HTTP 协议(四):完善 C++ HTTP 服务器:从协议原理到生产级实现
linux·运维·服务器·c语言·网络·c++·http
牛油果子哥q24 分钟前
【C++前置声明与头文件】C++前置声明与头文件深度精讲:重复包含、循环依赖、重复定义报错、工程编译架构与实战解决方案
开发语言·c++
少司府25 分钟前
C++进阶:map和set的使用
开发语言·数据结构·c++·容器·stl·set·map
程序喵大人27 分钟前
C++ 程序员转型 AI Infra 学习路线
c++·人工智能·学习·ai infra
cpp_250129 分钟前
P11375 [GESP202412 六级] 树上游走
数据结构·c++·算法·题解·洛谷·树形结构·gesp六级
此生决int33 分钟前
算法从入门到精通——字符串
数据结构·c++·算法·蓝桥杯
basketball61635 分钟前
设计模式入门:7. 策略模式详解 C++实现
c++·设计模式·策略模式
Je1lyfish38 分钟前
CMU15-445 (2025 Fall/2026 Spring) Project#4 - Concurrency Control
开发语言·数据库·c++·笔记·后端·算法·系统架构