P1541 [NOIP2010 提高组] 乌龟棋

题目背景    记忆化搜索

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

题目描述

乌龟棋的棋盘是一行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≤121≤N≤30,1≤M≤12。

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

对于100\%100%的数据有1≤N≤350,1≤M≤1201≤N≤350,1≤M≤120,且44种爬行卡片,每种卡片的张数不会超过4040;0≤a_i≤100,1≤i≤N,1≤b_i≤4,1≤i≤M0≤ai​≤100,1≤iN,1≤bi​≤4,1≤iM

 

 

 

复制代码
#include<cstdio>

#include<cstring>

using namespace std;

const int M=45;

 

int dp[M][M][M][M];

int a[355];

void dfs(int x1,int x2,int x3,int x4){

       int &ans=dp[x1][x2][x3][x4];//用ans表示较长的名字

       if(ans>0) {

              return ;

       }

       if(x1>0){

              dfs(x1-1,x2,x3,x4);

              if(ans<dp[x1-1][x2][x3][x4]){

                     ans=dp[x1-1][x2][x3][x4];

              }

       }

       if(x2>0){

              dfs(x1,x2-1,x3,x4);

              if(ans<dp[x1][x2-1][x3][x4]){

                     ans=dp[x1][x2-1][x3][x4];

              }

       }

       if(x3>0){

              dfs(x1,x2,x3-1,x4);

              if(ans<dp[x1][x2][x3-1][x4]){

                     ans=dp[x1][x2][x3-1][x4];

              }

       }

       if(x4>0){

              dfs(x1,x2,x3,x4-1);

              if(ans<dp[x1][x2][x3][x4-1]){

                     ans=dp[x1][x2][x3][x4-1];

              }

       }

       //四种情况

       ans+=a[x1 +x2*2+x3*3+x4*4];

}

int dfs1(int x1,int x2,int x3,int x4){

       int &ans=dp[x1][x2][x3][x4];

       if(ans>0){

              return 0;

       }

       int x;

       if(x1>0){

              x=dfs1(x1-1,x2,x3,x4);

              if(ans<x){

                     ans=x;

              }

       }

       if(x2>0){

              x=dfs1(x1,x2-1,x3,x4);

              if(ans<x){

                     ans=x;

              }

       }

       if(x3>0){

              x=dfs1(x1,x2-1,x3-1,x4);

              if(ans<x){

                     ans=x;

              }

       }

       if(x4>0){

              x=dfs1(x1,x2,x3,x4-1);

              if(ans<x){

                     ans=x;

              }

       }

        

       ans=ans+a[x1 + x2*2+ x3*3+ x4*4];

      

       return ans;

}

int b[5];

int main(){

       int n,m,x;

       scanf("%d%d",&n,&m);

       for(int i=0;i<n;i++){

              scanf("%d",&a[i]);

       }

       memset(b,0,sizeof(b));

       for(int i=0;i<m;i++){

              scanf("%d",&x);

              b[x]++;

       }//四种牌的张数

      

       memset(dp,0,sizeof(dp));

       dp[0][0][0][0]=a[0];//先获得首位上的分数

 

       dfs(b[1],b[2],b[3],b[4]);

       printf("%d",dp[b[1]][b[2]][b[3]][b[4]]);

       return 0;

}

//分阶段的决策问题
复制代码

 

posted @   killjoyskr  阅读(52)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示