POJ 3003 Spiderman’s workout
問題
n個の上り下りの記録が与えられる。
それぞれの数字は上り下りの距離であるが、その方向はわからない。
最初は0mの高さにいて、全ての上り下りを終えた時点でも0mの高さにいる。
上り下りの途中で高さが0mを下回ることはない。
この条件を満たす上で、途中の最大の高さが最も小さくなるように上り下りする。
そのような上り下りの仕方をどれか一つ出力せよ。
一つもない場合、IMPOSSIBLEを出力せよ。
制約条件
n≦40
上り下りの総距離≦1000
方針
dp[i][j]をi番目の上り下りを終えた時点でjmの地点にいるときの、今までで上ったもっとも高い高さとする。
これを更新していくようなDPをすれば答えが求まる。
ソースコード
int dp[41][1001],prev[41][1001]; char ans[50]; int main() { int cs; scanf("%d",&cs); while(cs--){ int n,h[40]; scanf("%d",&n); rep(i,n)scanf("%d",h+i); rep(i,n+1)rep(j,1001)dp[i][j]=inf; dp[0][0]=0; rep(i,n)rep(j,1001){ if(j+h[i]<=1000&&dp[i+1][j+h[i]]>max(j+h[i],dp[i][j])) prev[i+1][j+h[i]]=j, dp[i+1][j+h[i]]=max(j+h[i],dp[i][j]); if(j-h[i]>=0&&dp[i+1][j-h[i]]>dp[i][j]) prev[i+1][j-h[i]]=j, dp[i+1][j-h[i]]=dp[i][j]; } if(dp[n][0]==inf)puts("IMPOSSIBLE"); else{ ans[n]=0; int t=0; for(int i=n-1;i>=0;i--){ ans[i]=prev[i+1][t]<t?'U':'D'; t=prev[i+1][t]; } puts(ans); } } return 0; }