【动规递推】【NOIP2010】乌龟棋 tortoise

乌龟棋
tortoise

题目描述

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

 

     …… 
12345……N

输入格式

输入文件的每行中两个数之间用一个空格隔开。
第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 个整数,表示小明最多能得到的分数。

【输入输出样例1】

tortoise.in

9 5

6 10 14 2 8 8 18 5 17

1 3 1 2 1

tortoise.out 

73

 

【输入输出样例2】

tortoise.in

13 8

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

1 1 1 1 1 2 4 1

tortoise.out 

455

 

显然这是一道动规的题目,状态设计可以用四维f[a][b][c][d]来维护,表示f["1"的张数]["2"的张数]["3"的张数]["4"的张数]

方程就很显然了

      f[a][b][c][d]=max{(a>0)  f[a-1][b][c][d]+a[a*1+b*2+c*3+d*4],

                (b>0)  f[a][b-1][c][d]+a[a*1+b*2+c*3+d*4],

                (c>0)  f[a][b][c-1][d]+a[a*1+b*2+c*3+d*4],

                (d>0)  f[a][b][c][d-1]+a[a*1+b*2+c*3+d*4]}

当然,由于第一个点自动得分,所以f[0][0][0][0]=a[1](这也是为什么我们只用计算每一部终点的得分,可以确保起点已经计算)

C++ Code

/*
C++ Code
http://blog.csdn.net/jiangzh7
*/
#include<cstdio>
#define MAXN 400

int n,m,a[MAXN],sum[5];
int f[50][50][50][50];

int main()
{
    freopen("tortoise.in","r",stdin);
    freopen("tortoise.out","w",stdout);
    scanf("%d%d",&n,&m);
    int i,j,k,t,x;
    for(i=1;i<=n;i++) scanf("%d",&a[i]);
    for(i=1;i<=m;i++) {scanf("%d",&x);sum[x]++;}
    f[0][0][0][0]=a[1];
    for(i=0;i<=sum[1];i++)
        for(j=0;j<=sum[2];j++)
            for(k=0;k<=sum[3];k++)
                for(t=0;t<=sum[4];t++)
                {
                    if(i>=1)f[i][j][k][t]>?=f[i-1][j][k][t]+a[1+i*1+j*2+k*3+t*4];
                    if(j>=1)f[i][j][k][t]>?=f[i][j-1][k][t]+a[1+i*1+j*2+k*3+t*4];
                    if(k>=1)f[i][j][k][t]>?=f[i][j][k-1][t]+a[1+i*1+j*2+k*3+t*4];
                    if(t>=1)f[i][j][k][t]>?=f[i][j][k][t-1]+a[1+i*1+j*2+k*3+t*4];
                }
    printf("%d",f[sum[1]][sum[2]][sum[3]][sum[4]]);
    return 0;
}

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值