首页 > 代码库 > 10 noip 乌龟棋 解题报告

10 noip 乌龟棋 解题报告

 

题目描述 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%的数据有1 ≤ N≤ 30,1 ≤M≤ 12。

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

过20。

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

超过40;0 ≤ ai ≤ 100,1 ≤ i ≤ N;1 ≤ bi ≤ 4,1 ≤ i ≤M。输入数据保证N−1=ΣM

i b

1

 

  这个题目具有明显的无后效性,所以他是一个典型的动归。我认为,对于一个动归题目的分析,一定要从决策和状态入手。

  首先我们来看状态,这个题目的状态很简单,就是乌龟所在什么格子,且用了什么卡片。然后是决策,决策也很简单,就是下一张要出什么卡片。

  我们再来看状态和决策的关系,我们假设四种卡片都存在。如果乌龟走了n步,那么他之前应该在n-1,n-2,n-3,n-4中的某个格子上,那么乌龟此时能去到的最大值,就是在这四个格子上能去到的最大值加上自己当前格子的数值。

  然后我们就得到了dP方程

  f[n]=max(f[n-1,f[n-2],f[n-3],f[n-4])+a[n]

  其中f[n]表示到当前格子所能去到的最大分数,a[n]表示当前格子的分数。

  但是,我们肯定不能从1到n去求,因为卡片的张数是有限的,这样求无法限制卡片张数,于是我毅然决然的把方程改成了下面这个东西。

  f[i,j,k,t]:=max(f[i-1,j,k,t],f[i,j-1,k,t],f[i,j,k-1,t],f[i,j,k,t-1])+a[i*1+j*2+k*3+t*4+1];

  因为每张卡片最多40张,所以时间复杂度还可以忍受。

  

  代码风格略渣,不喜勿喷。

 1 var 2  n,m,i,j,k,t,x:longint; 3  f:array[-1..40,-1..40,-1..40,-1..40]of longint; 4  a:array[0..350]of longint; 5  mn:array[1..4]of longint; 6 function max(q,w,e,r:longint):longint; //判断最大值 7 begin 8  max:=q; 9  if (w>max) then max:=w;10  if (e>max) then max:=e;11  if (r>max) then max:=r;12 end;13 begin14  readln(n,m);15  fillchar(a,sizeof(a),0);16  fillchar(f,sizeof(f),0);17  for i:=1 to n do18   read(a[i]);19  fillchar(mn,sizeof(mn),0);20  for i:=1 to m do21   begin22    read(x);23    inc(mn[x]);24   end;25  for i:=0 to mn[1] do  //dp26   for j:=0 to mn[2] do27    for k:=0 to mn[3] do28     for t:=0 to mn[4] do29     f[i,j,k,t]:=max(f[i-1,j,k,t],f[i,j-1,k,t],f[i,j,k-1,t],f[i,j,k,t-1])+a[i*1+j*2+k*3+t*4+1];30  writeln(f[mn[1],mn[2],mn[3],mn[4]]);31 end.

 

10 noip 乌龟棋 解题报告