noip2010 乌龟棋

题目描述

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

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

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

 

【数据范围】
对于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=Σb_i (1<=i<=M)

输入

每行中两个数之间用一个空格隔开。
第1 行2 个正整数N 和M,分别表示棋盘格子数和爬行卡片数。
第2 行N 个非负整数,a1, a2, ……, aN,其中ai 表示棋盘第i 个格子上的分数。
第3 行M 个整数,b1,b2, ……, bM,表示M 张爬行卡片上的数字。
输入数据保证到达终点时刚好用光M 张爬行卡片,即N−;;1=Σb_i (1<=i<=M)

输出

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

样例输入

9 5 6 10 14 2 8 8 18 5 17 1 3 1 2 1

样例输出

73

解题思路:记得这道题好像老师以前就已经让做过了,很熟悉,其实就是动规,规划各种卡片的施用数量使得分数最高即可。而动规需要记录当前状态,即表示出当前的位置,剩余卡片的数量位置容易记录,用一个变量就可以了,那么怎么记录卡片数量呢?

仔细观察数据可以发现,卡牌只有1.2.3.4四种并且都不超过40张,那么就可以再建四个数组表示卡牌的使用数量。同时有    当前位置+i(1的使用数量)*1+j(..同前)*2+k(同前)*3+l(同前)*4=n,

即它们彼此已知四个量就可求出另外一个量(所以位置就。动规方程如下:

  f[i,j,k,l]:={分别使用i,j,k,l张牌所能获得的最大分数}:=max(f[i-1,j,k,l],f[i,j-1,k,l],f[i,j,k-1,l],f[i,j,k,l-1]){即之前的分数和}+a[i+2*j+3*k+4*l+1]{目前位置的分数}

  这里要注意的是棋盘的第一个格子是起点,也就是当 f[0,0,0,0]时是等于第一个格子的分数的。也就是说,f[I,j,k,l]时也是格子数减一,那么a[i+j*2+k*3+l*4+1]就解释的通了;既是全部用完(i+j*2+k*3+l*4)也比格子数少一,况且我们还要拿第一个格子里的分数嘛,现在是

AC程序:

 

var 

  i,j,k,l,m,n:longint;

  a:array[1..350]oflongint;

  b:array[1..120]oflongint;

  c:array[1..4]oflongint;

  f:array[-1..40,-1..40,-1..40,-1..40]oflongint;

functionmax(x,y,g,t:longint):longint;

  begin

    max:=x;

    ify>max thenmax:=y;

    ifg>max thenmax:=g;

    ift>max thenmax:=t;   //比较大小

  end;

begin

  readln(n,m);//读入格子数,牌的个数

  fillchar(c,sizeof(c),0);

  fillchar(f,sizeof(f),0);//初始化

  fori:=1ton do

    read(a[i]);   //读入格子的分数

  fori:=1tom do

    begin

    read(b[i]);

    inc(c[b[i]]);

    end;//统计每种牌的数量

  f[0,0,0,0]:=a[1];

  fori:=0toc[1] do

    forj:=0toc[2] do

      fork:=0toc[3] do

        forl:=0toc[4] do

        f[i,j,k,l]:=max(f[i-1,j,k,l],f[i,j-1,k,l],f[i,j,k-1,l],f[i,j,k,l-1])+a[i+2*j+3*k+4*l+1];//即上述的动规过程。

  writeln(f[c[1],c[2],c[3],c[4]]);输出

End.

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值