题意:
和往常Hanoi问题不一样,这题给出每种操作的花费,用一个矩阵表示cost[i][j],表示从i号移动到j号的花费。问如何移动使得1中的全部圆块移动到3花费最小。
题解:
很明显要用记忆优化,那么正常的Hanoi问题移动的递归是这样的 dfs(l,n-1,x),move(l,r),dfs(x,n-1,r)
但是这题要求得最小花费决策肯定不止这一个,其实还可以这样 dfs(l,n-1,r),move(l,x),dfs(r,n-1,l),
move(x,r),dfs(l,n-1,r) 。其实就这两方案可以放,那么很显然状态方程就出来了。
dp[l][n][r] = max{ dfs(l,n-1,r)+cost[l][r] , dfs(l,n-1,r)*2+dfs(r,n-1,l)+cost[l][x]+cost[x][r] }
注意一点,当只有一个方块移动时,要判断cost[l][r],cost[l][x]+cost[x][r]那个更小。
#include<iostream> #include<math.h> #include<stdio.h> #include<algorithm> #include<string.h> #include<vector> #include<map> using namespace std; typedef long long ll; const int oo=0x3f3f3f3f; const ll OO=1LL<<61; const ll MOD=2147483647; const int maxn=5005; ll dp[4][45][4]; int cost[4][4]; ll Hanoi(int l,int n,int r) { if(dp[l][n][r]!=-1)return dp[l][n][r]; int x=6-l-r; if(n==1) return dp[l][n][r]=min(cost[l][r],cost[l][x]+cost[x][r]); ll ans1=Hanoi(l,n-1,x)+Hanoi(x,n-1,r)+cost[l][r]; ll ans2=Hanoi(l,n-1,r)*2+Hanoi(r,n-1,l)+cost[l][x]+cost[x][r]; return dp[l][n][r]=min(ans1,ans2); } int main() { int n; memset(dp,-1,sizeof dp); for(int i=1;i<=3;i++) for(int j=1;j<=3;j++) scanf("%d",&cost[i][j]); scanf("%d",&n); cout<<Hanoi(1,n,3)<<endl; return 0; } /** 0 2 2 1 0 100 1 2 0 3 */