題目:大意是說 有n個台子,編號1-n,開始時,有一只猴子站在編號1的台子上,猴子可以自由地蹦到兩側的台子上,每次i移動話費的時間是一秒,有個人每秒鐘仍一個盤子到其中的一個台子上,問在猴子移動次數不超過t的情況下,猴子能接到的最多的盤子數。
方法:一個dp的題目,原來看到過,還不會做,直到最近在做dp的題目,才解決了這個題目。
使用一個三維數組dp[i][j][k],i代表當前進行到第i秒鐘,也是第i盤子扔出的時間,j代表當前移動的步數,k代表當前所處的台子編號。
很容易能找到狀態轉移方程:dp[i][j][k]=max(dp[i-1][j][k],max(dp[i-1][j-1][k-1]),dp[i-1][j-1][k+1])+(f[i]==k);
當然本題的f[i]是有相應的值的,需要在進行一下處理。
已經找到了狀態轉移方程之後,還有一些要注意的問題就是需要進行一下限制,比如:題目中已經說到了猴子的初始位置是一號台子,而不是隨意的,所以這裡就需要注意了,當進行到第i個盤子的時候,假設j>i,從一開始到此時猴子的移動范圍為1-i+1這幾個台子,所以要加一個限制條件了,因為這個錯了n次。
代碼:
#include#include #include using namespace std; struct node { int d,v; }z[105]; int dp[105][105][105]; int main() { int n,m,t,sum=1; int i,j,k; while(scanf("%d%d%d",&n,&m,&t)!=EOF) { int mas=0; memset(dp,0,sizeof(dp)); for(i=1;i<=m;i++) scanf("%d%d",&z[i].d,&z[i].v); t++; for(i=1;i<=m;i++) for(j=1;j<=t&&j<=i+1;j++) //這裡加了限制,還有為了方便dp數組中j-1不使得數組越界,我把移動次數用1代表0,2代表1...這也是為什麼上面t++ for(k=1;k<=n&&k<=j;k++) //k>j就沒必要更新了 { dp[i][j][k]=max(dp[i-1][j][k],max(dp[i-1][j-1][k-1],dp[i-1][j-1][k+1])); if(z[i].d==k) dp[i][j][k]+=z[i].v; if(mas