nyist 740 “炫舞家“ST(动态规划)
dp[i][j][k]:表示第i次踩踏后两脚的位置j,k
先固定一只脚的位置j,第i次踩踏后,状态为dp[i][j][a[i]]或者dp[i][a[i]][j],其中a[i]表示第i个输入的元素,则有状态方程:
x=dp[i-1][k][j]+cost[k][a[i]]; 是通过k踩过来的,cost[k][a[i]]表示k->a[i]的花费。
y=dp[i-1][j][k]+cost[k][a[i]]; 是通过k踩过来的,cost[k][a[i]]表示k->a[i]的花费。
dp[i][j][a[i]]=dp[i][a[i]][j]=min(x,y);
答案:ans=min(dp[n][j][a[i]])
#include <iostream> #include <math.h> using namespace std; int a[10005],dp[10005][6][6]; int cost[6][6]; int main(int argc, char *argv[]) { int i,j,k,ans,t,n,x,y; while(cin>>t&&t) { a[1]=t; for(n=2;;n++) { cin>>a[n]; if(!a[n]) break; } for(i=0;i<5;i++) for(j=0;j<5;j++) cost[i][j]=100000005; cost[0][1]=cost[0][2]=cost[0][3]=cost[0][4]=2; cost[1][2]=cost[2][1]=cost[2][3]=cost[3][2]=cost[3][4]=cost[4][3]=cost[4][1]=cost[1][4]=3; cost[1][3]=cost[3][1]=cost[2][4]=cost[4][2]=4; cost[1][1]=cost[2][2]=cost[3][3]=cost[4][4]=1; for(i=0;i<=n;i++) for(j=0;j<5;j++) for(k=0;k<5;k++) dp[i][j][k]=100000005; dp[0][0][0]=0;ans=100000005; for(i=1;i<n;i++) { for(j=0;j<5;j++)//没动的脚 { if(j==a[i]) continue; x=y=100000005; for(k=0;k<5;k++) //左脚踩 { if(k!=j||k+j==0) if(x>dp[i-1][k][j]+cost[k][a[i]]) x=dp[i-1][k][j]+cost[k][a[i]]; } for(k=0;k<5;k++) //右脚踩 { if(k!=j||k+j==0) if(y>dp[i-1][j][k]+cost[k][a[i]]) y=dp[i-1][j][k]+cost[k][a[i]]; } if(x>y) x=y; dp[i][j][a[i]]=dp[i][a[i]][j]=x; //cout<<i<<" -> "<<a[i]<<" -> "<<j<<" "<<dp[i][a[i]][j]<<endl; if(ans>dp[n-1][j][a[i]]) ans=dp[n-1][j][a[i]]; } } cout<<ans<<endl; } return 0; }