codefores 392B Tower of Hanoi (记忆搜索)

题意:

和往常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

*/







你可能感兴趣的:(codefores 392B Tower of Hanoi (记忆搜索))