2018年6月6號(P1541 烏龜棋)
今天做提高組題時,無意間看見了這道題就立刻興致勃勃的去做,結果突然發現自己不會dp了,死磕了一下發現自己根本不會
沒辦法就只好點開題解,瞬間明白(突然覺得自己好笨):
題目:
題目背景
小明過生日的時候,爸爸送給他一副烏龜棋當作禮物。
題目描述
烏龜棋的棋盤是一行 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≤i≤N,1≤bi?≤4,1≤i≤M 。
代碼君送上:
1 #include<bits/stdc++.h> 2 using namespace std; 3 long long dp[41][41][41][41],n,m;//f[i][j][k][l]表示四種不相同的卡片 4 int a[351],b[5],c; 5 int main() 6 { 7 cin>>n>>m; 8 for(int i=1;i<=n;i++)cin>>a[i]; 9 dp[0][0][0][0]=a[1]; 10 for(int i=1;i<=m;i++) 11 { 12 cin>>c; 13 b[c]++;//桶排序來記入不同卡牌 14 } 15 for(int i=0;i<=b[1];i++) 16 for(int j=0;j<=b[2];j++) 17 for(int k=0;k<=b[3];k++) 18 for(int l=0;l<=b[4];l++)//暴力枚舉,每一種卡牌使用數量 19 { 20 int t=a[i+2*j+3*k+4*l+1];//加起來 21 if(i)dp[i][j][k][l]=max(dp[i-1][j][k][l]+t,dp[i][j][k][l]); 22 if(j)dp[i][j][k][l]=max(dp[i][j-1][k][l]+t,dp[i][j][k][l]); 23 if(k)dp[i][j][k][l]=max(dp[i][j][k-1][l]+t,dp[i][j][k][l]); 24 if(l)dp[i][j][k][l]=max(dp[i][j][k][l-1]+t,dp[i][j][k][l]);//動態轉移方程
//至於這個(a!=0),顯然,你要是調用F[a-1][b][c][d],肯定得保證a-1>=0吧。a顯然作為卡1個數不可能<0,故取(a!=0)即可根據多維背包的思想,背包DP幾個“價值”(即爬行牌種類)開幾維即可 25 } 26 cout<<dp[b[1]][b[2]][b[3]][b[4]]; 27 return 0; 28 }
根據題解
寫出來就是舒服
2018年6月6號(P1541 烏龜棋)