NOIP201006乌龟棋

试题描述

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

输入
输入每行中两个数之间用一个空格隔开。 
第 1 行2 个正整数 N和 M,分别表示棋盘格子数和爬行卡片数。 
    第 2 行 N个非负整数,a1, a2,  ……, aN,其中 ai 表示棋盘第 i 个格子上的分数。 
   第 3 行M 个整数,b1,b2, ……, bM,表示 M 张爬行卡片上的数字。 
  输入数据保证到达终点时刚好用光 M 张爬行卡片,即 N?1= ∑Mib1。 
输出
输出只有 1行,1 个整数,表示小明最多能得到的分数。 
输入示例
【输入样例 1】
9 5 
6 10 14 2 8 8 18 5 17 
1 3 1 2 1 

【输入样例 2】
13 8 
4 96 10 64 55 13 94 53 5 24 89 8 30
1 1 1 1 1 2 4 1 
输出示例
【输出样例 1】
73
【输出样例 2】
455
其他说明
【输入输出样例 1 说明】小明使用爬行卡片顺序为 1,1,3,1,2,得到的分数为 6+10+14+8+18+17=73。注意,由于起点是 1,所以自动获得第 1 格的分数 6。

【数据范围】对于 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=∑Mib1。
 

动态规划。

 1 #include <iostream>
 2 
 3 using namespace std;
 4 long long a[355],f[41][41][41][41]={0};
 5 int read() //输入模板 
 6 {
 7     int x=0,f=1;
 8     char ch=getchar();
 9     while(ch<'0'||ch>'9')
10     {
11         if(ch=='-') f=-1;
12         ch=getchar();
13     }
14     while(ch>='0'&&ch<='9')
15     {
16         x=x*10+ch-'0';
17         ch=getchar();
18     }
19     return x*f;
20 } 
21 int main()
22 {
23     int n,m,b1=0,b2=0,b3=0,b4=0;
24     n=read();m=read();
25     for(int i=1;i<=n;i++) a[i]=read();
26     for(int i=1;i<=m;i++)
27     {
28         int temp;
29         temp=read();
30         if(temp==1) b1++;
31         else if(temp==2) b2++;
32         else if(temp==3) b3++;
33         else b4++;
34     }
35     f[0][0][0][0]=a[1];
36     for(int x4=0;x4<=b4;x4++)
37     {
38         for(int x3=0;x3<=b3;x3++)
39         {
40             for(int x2=0;x2<=b2;x2++)
41             {
42                 for(int x1=0;x1<=b1;x1++)
43                 {
44                     int A=0,B=0,C=0,D=0;
45                     if(x1>0) A=f[x1-1][x2][x3][x4]+a[x1+2*x2+3*x3+4*x4+1];
46                     if(x2>0) B=f[x1][x2-1][x3][x4]+a[x1+2*x2+3*x3+4*x4+1];
47                     if(x3>0) C=f[x1][x2][x3-1][x4]+a[x1+2*x2+3*x3+4*x4+1];
48                     if(x4>0) D=f[x1][x2][x3][x4-1]+a[x1+2*x2+3*x3+4*x4+1];
49                     if(x1==0 && x2==0 && x3==0 && x4==0) continue;
50                     else f[x1][x2][x3][x4]=max(max(A,B),max(C,D));
51                 }
52             }
53         }
54     }
55     printf("%d",f[b1][b2][b3][b4]);
56     system("pause");
57     return 0;
58 }
NOIP201006乌龟棋
原文地址:https://www.cnblogs.com/YXY-1211/p/5468386.html