CJOJ 1087 【NOIP2010】乌龟棋 / Luogu 1541 乌龟棋(动态规划)
CJOJ 1087 【NOIP2010】烏龜棋 / Luogu 1541 烏龜棋(動態規劃)
Description
小明過生日的時候,爸爸送給他一副烏龜棋當作禮物。
烏龜棋的棋盤是一行N個格子,每個格子上一個分數(非負整數)。棋盤第1格是唯一的起點,第N格是終點,游戲要求玩家控制一個烏龜棋子從起點出發走到終點。
烏龜棋中M張爬行卡片,分成4種不同的類型(M張卡片中不一定包含所有4種類型的卡片,見樣例),每種類型的卡片上分別標有1、2、3、4四個數字之一,表示使用這種卡片后,烏龜棋子將向前爬行相應的格子數。游戲中,玩家每次需要從所有的爬行卡片中選擇一張之前沒有使用過的爬行卡片,控制烏龜棋子前進相應的格子數,每張卡片只能使用一次。
游戲中,烏龜棋子自動獲得起點格子的分數,并且在后續的爬行中每到達一個格子,就得到該格子相應的分數。玩家最終游戲得分就是烏龜棋子從起點到終點過程中到過的所有格子的分數總和。
很明顯,用不同的爬行卡片使用順序會使得最終游戲的得分不同,小明想要找到一種卡片使用順序使得最終游戲得分最多。
現在,告訴你棋盤上每個格子的分數和所有的爬行卡片,你能告訴小明,他最多能得到多少分嗎?
Input
每行中兩個數之間用一個空格隔開。
第1行2個正整數N和M,分別表示棋盤格子數和爬行卡片數。
第2行_N個非負整數,a1, a2,……, aN,其中ai表示棋盤第i個格子上的分數。
第3行M個整數,b1,b2,……, bM,表示M張爬行卡片上的數字。
輸入數據保證到達終點時剛好用光M張爬行卡片,即N?1=ΣM (ΣM表示M張卡片數字的和)
Output
輸出只有1行,1個整數,表示小明最多能得到的分數。
Sample Input
9 5
6 10 14 2 8 8 18 5 17
1 3 1 2 1
Sample Output
73
Http
CJOJ:http://oj.changjun.com.cn/problem/detail/pid/1087
Luogu:https://www.luogu.org/problem/show?pid=1541
Source
動態規劃
解決思路
我們首先想到的是令F[x][a][b][c][d]表示走到x格時用了a格爬1格,b個爬2格,c個爬3格,d個爬4個的卡片所能有的最大得分。那么我們就能得到一個初始的動態轉移方程
\[F[x][a][b][c][d]=max \begin{cases} F[x-1][a-1][b][c][d]& \text{a!=0}\\F[x-2][a][b-1][c][d]& \text{b!=0} \\ F[x-3][a][b][c-1][d]& \text{c!=0} \\ F[x-4][a][b][c][d-1]& \text{d!=0}\end{cases} +Value[x]\]
但是這樣是通不過空間限制的。題中已經給出了用這M張卡片一定能到達n格,所以我們可以省掉x那一維數組,直接用a,b,c,d推出x,所以動態轉移方程為
\[F[a][b][c][d]=max \begin{cases} F[a-1][b][c][d]& \text{a!=0}\\F[a][b-1][c][d]& \text{b!=0} \\ F[a][b][c-1][d]& \text{c!=0} \\ F[a][b][c][d-1]& \text{d!=0}\end{cases} +Value[a+b*2+c*3+d*4+1]\]
注意最后要+1,因為起始格是第一格。
為了簡便,我們還是使用記憶化的方法。
代碼
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std;const int maxN=351; const int maxC=41; const int inf=2147483647;int n,m; int Card[10]={0}; int Value[maxN]; int F[maxC][maxC][maxC][maxC];int dfs(int a,int b,int c,int d);int main() {int x;cin>>n>>m;for (int i=1;i<=n;i++)cin>>Value[i];for (int i=1;i<=m;i++){cin>>x;Card[x]++;//直接累加到同類卡片的計數器中}memset(F,-1,sizeof(F));F[0][0][0][0]=Value[1];F[Card[1]][Card[2]][Card[3]][Card[4]]=dfs(Card[1],Card[2],Card[3],Card[4]);cout<<F[Card[1]][Card[2]][Card[3]][Card[4]]<<endl;return 0; }int dfs(int a,int b,int c,int d)//記憶化搜索 {if (F[a][b][c][d]!=-1)return F[a][b][c][d];int k=a+b*2+c*3+d*4+1;if (a!=0)F[a][b][c][d]=max(F[a][b][c][d],dfs(a-1,b,c,d));if (b!=0)F[a][b][c][d]=max(F[a][b][c][d],dfs(a,b-1,c,d));if (c!=0)F[a][b][c][d]=max(F[a][b][c][d],dfs(a,b,c-1,d));if (d!=0)F[a][b][c][d]=max(F[a][b][c][d],dfs(a,b,c,d-1));F[a][b][c][d]+=Value[k];return F[a][b][c][d]; }轉載于:https://www.cnblogs.com/SYCstudio/p/7138161.html
總結
以上是生活随笔為你收集整理的CJOJ 1087 【NOIP2010】乌龟棋 / Luogu 1541 乌龟棋(动态规划)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Leetcode:Palindrome
- 下一篇: HP Unix vsftp服务配置