CODE[VS] 1068 乌龟棋

题目描述 Description

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

…… 1 2 3 4 5 ……N 乌龟棋中M张爬行卡片,分成4种不同的类型(M张卡片中不一定包含所有4种类型 的卡片,见样例),每种类型的卡片上分别标有1、2、3、4四个数字之一,表示使用这种卡 片后,乌龟棋子将向前爬行相应的格子数。游戏中,玩家每次需要从所有的爬行卡片中选择 一张之前没有使用过的爬行卡片,控制乌龟棋子前进相应的格子数,每张卡片只能使用一次。 游戏中,乌龟棋子自动获得起点格子的分数,并且在后续的爬行中每到达一个格子,就得到 该格子相应的分数。玩家最终游戏得分就是乌龟棋子从起点到终点过程中到过的所有格子的 分数总和。 很明显,用不同的爬行卡片使用顺序会使得最终游戏的得分不同,小明想要找到一种卡 片使用顺序使得最终游戏得分最多。 现在,告诉你棋盘上每个格子的分数和所有的爬行卡片,你能告诉小明,他最多能得到 多少分吗?

输入描述 Input Description

输入的每行中两个数之间用一个空格隔开。 第1行2个正整数N和M,分别表示棋盘格子数和爬行卡片数。 第2行N个非负整数,a1a2……aN

,其中ai表示棋盘第i个格子上的分数。 第3行M个整数,b1b2……bM

,表示M张爬行卡片上的数字。 输入数据保证到达终点时刚好用光M张爬行卡片,即N - 1=∑(1->M) bi

输出描述 Output Description

输出一行一个整数

样例输入 Sample Input

13 8

4 96 10 64 55 13 94 53 5 24 89 8 30

1 1 1 1 1 2 4 1

样例输出 Sample Output

455

数据范围及提示 Data Size & Hint

【数据范围】

对于30%的数据有 N 30M 12

对于50%的数据有 N 120M 50,且种爬行卡片,每种卡片的张数不会超

20

对于100%的数据有 N 350M 120,且种爬行卡片,每种卡片的张数不会

超过40 a 100  N b 4 M。输入数据保证N−1=ΣM

b

1


这个题一个背包型的DP题目,针对这个题目,我们可以把总的路程看作是一个背包所能承受的最大的重量,然后对应每个格子相当于价值,我们要有效的选取所能选取的最有价值的物品
我们的策略是用一个四维的数组,这个数组可以四个坐标分别代表1,2,3,4步数出现的次数.然后要求最后用完所有的步数时最优的策略.
动态转移方程就是在该状态比前一状态加上该状态下的价值要低的话,更新状态,否则跳过当前的物品.最后打好的表的第dp[1的数量][2的数量][3的数量][4的数量]就是我们要求的最后的状态中的最佳状态.
代码如下:
/*************************************************************************
    > File Name: 乌龟棋.cpp
    > Author: zhanghaoran
    > Mail: chilumanxi@gmail.com
    > Created Time: 2015年06月22日 星期一 19时25分03秒
 ************************************************************************/

#include <iostream>
#include <algorithm>
#include <utility>
#include <cstring>
#include <cstdio>
using namespace std;

int N, M;
int a[351];
int dp[50][50][50][50];
int x;
int b[5];
int main(void){
    freopen("in.txt", "r", stdin);
	cin >> N >> M;
	memset(dp, 0, sizeof(dp));
	memset(b, 0, sizeof(b));
	for(int i = 0; i < N; i++)
		cin >> a[i];
	for(int j = 0; j < M; j ++){
		cin >> x;
		b[x] ++;
	}
	dp[0][0][0][0] = a[0];
	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 ++){
					if(i >= 1) dp[i][j][k][l] = dp[i][j][k][l] > dp[i - 1][j][k][l] + a[i + 2 * j + 3 * k + 4 * l] ? dp[i][j][k][l] : dp[i - 1][j][k][l] + a[i + 2 * j + 3 * k + 4 * l];
					if(j >= 1) dp[i][j][k][l] = dp[i][j][k][l] > dp[i][j - 1][k][l] + a[i + 2 * j + 3 * k + 4 * l] ? dp[i][j][k][l] : dp[i][j - 1][k][l] + a[i + 2 * j + 3 * k + 4 * l];
					if(k >=1) dp[i][j][k][l] = dp[i][j][k][l] > dp[i][j][k - 1][l] + a[i + 2 * j + 3 * k + 4 * l] ? dp[i][j][k][l] : dp[i][j][k - 1][l] + a[i + 2 * j + 3 * k + 4 * l];
					if(l >= 1) dp[i][j][k][l] = dp[i][j][k][l] > dp[i][j][k][l - 1] + a[i + 2 * j + 3 * k + 4 * l] ? dp[i][j][k][l] : dp[i][j][k][l - 1] + a[i + 2 * j + 3 * k + 4 * l];
				}
			}
		}
	}
	cout << dp[b[1]][b[2]][b[3]][b[4] ] << endl;
	return 0;
}

代码稍微写的有点啰嗦.
原文地址:https://www.cnblogs.com/chilumanxi/p/5136125.html