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;

}


 


 

你可能感兴趣的:(动态规划)