• NOIP 2010 乌龟棋


    JDOJ 1604: [NOIP2010]乌龟棋 T2

    https://neooj.com/oldoj/problem.php?id=1604

    洛谷 P1541 乌龟棋

    https://www.luogu.org/problemnew/show/P1541

    题目背景

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

    题目描述

    乌龟棋的棋盘是一行NN个格子,每个格子上一个分数(非负整数)。棋盘第1格是唯一的起点,第NN格是终点,游戏要求玩家控制一个乌龟棋子从起点出发走到终点。

    乌龟棋中MM张爬行卡片,分成4种不同的类型(MM张卡片中不一定包含所有44种类型的卡片,见样例),每种类型的卡片上分别标有1,2,3,41,2,3,4四个数字之一,表示使用这种卡片后,乌龟棋子将向前爬行相应的格子数。游戏中,玩家每次需要从所有的爬行卡片中选择一张之前没有使用过的爬行卡片,控制乌龟棋子前进相应的格子数,每张卡片只能使用一次。

    游戏中,乌龟棋子自动获得起点格子的分数,并且在后续的爬行中每到达一个格子,就得到该格子相应的分数。玩家最终游戏得分就是乌龟棋子从起点到终点过程中到过的所有格子的分数总和。

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

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

    输入输出格式

    输入格式:

    每行中两个数之间用一个空格隔开。

    11行22个正整数N,MN,M,分别表示棋盘格子数和爬行卡片数。

    22行NN个非负整数,a_1,a_2,…,a_Na1,a2,,aN,其中a_iai表示棋盘第ii个格子上的分数。

    33行MM个整数,b_1,b_2,…,b_Mb1,b2,,bM,表示M张爬行卡片上的数字。

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

    输出格式:

    11个整数,表示小明最多能得到的分数。

    输入输出样例

    输入样例#1: 复制
    9 5
    6 10 14 2 8 8 18 5 17
    1 3 1 2 1
    
    输出样例#1: 复制
    73
    

    说明

    每个测试点1s1s

    小明使用爬行卡片顺序为1,1,3,1,21,1,3,1,2,得到的分数为6+10+14+8+18+17=736+10+14+8+18+17=73。注意,由于起点是11,所以自动获得第11格的分数66。

    对于30\%30%的数据有1≤N≤30,1≤M≤121N30,1M12。

    对于50\%50%的数据有1≤N≤120,1≤M≤501N120,1M50,且44种爬行卡片,每种卡片的张数不会超过2020。

    对于100\%100%的数据有1≤N≤350,1≤M≤1201N350,1M120,且44种爬行卡片,每种卡片的张数不会超过4040;0≤a_i≤100,1≤i≤N,1≤b_i≤4,1≤i≤M0ai100,1iN,1bi4,1iM。

    我认为这道题是线性DP的难题,但是我还是认为这道题用的是背包思想。

    看了大佬们的解答,这道题属于多重背包,然鹅我并不会。

    所以我用我缓慢的大脑尝试着切了这道题。

    四位数组DP;

    我们只需要决策,针对于每张卡,放还是不放。

    诶?好像是01背包的思想?

    01背包我会啊,然后我就憋了一份代码。

    AC

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int n,m;
    int a[351];
    int dp[40][40][40][40];
    int z[4];
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        dp[0][0][0][0]=a[1];
        for(int i=1;i<=m;i++)
        {
            int x;
            scanf("%d",&x);
            z[x]++;
        }
        for(int i=0;i<=z[1];i++)
            for(int j=0;j<=z[2];j++)
                for(int k=0;k<=z[3];k++)
                    for(int l=0;l<=z[4];l++)
                    {
                        int round=i+j*2+k*3+l*4+1;
                        if(i)
                            dp[i][j][k][l]=max(dp[i][j][k][l],dp[i-1][j][k][l]+a[round]);
                        if(j)
                            dp[i][j][k][l]=max(dp[i][j][k][l],dp[i][j-1][k][l]+a[round]);
                        if(k)
                            dp[i][j][k][l]=max(dp[i][j][k][l],dp[i][j][k-1][l]+a[round]);
                        if(l)
                            dp[i][j][k][l]=max(dp[i][j][k][l],dp[i][j][k][l-1]+a[round]);
                    }
        printf("%d",dp[z[1]][z[2]][z[3]][z[4]]);
        return 0;
    }
  • 相关阅读:
    Android牟利之道(四)如何推广你的产品,即你的APP
    android权限
    OpenGL 中文 API
    为何不能上网浏览网页 但是可以用QQ聊天
    安装任何软件都提示不能访问windows Installer服务
    初识WAP
    用asp.net 2.0实现网站二级域名(转)
    Visual Studio .NET已检测到指定的Web服务器运行的不是ASP.NET 1.1 版
    用EasyBoot轻松做启动光盘
    我心中的痛房子
  • 原文地址:https://www.cnblogs.com/fusiwei/p/11238698.html
Copyright © 2020-2023  润新知