CF392BTower of Hanoi(记忆化搜索)

记搜好题

预处理

题目给出了将一个盘从x移到y的代价(代码中为a[][]),当我们知道这并不是最优的

就像最短路floyd一样松弛操作预处理得到两柱之间最优值b[][]

for(int i=1;i<=3;i++) for(int j=1;j<=3;j++) scanf("%lld",&a[i][j]),b[i][j]=a[i][j]; for(int i=1;i<=3;i++) for(int j=1;j<=3;j++) if(i!=j) for(int k=1;k<=3;k++) if(k!=i&&k!=j) b[i][j]=min(b[i][j],b[i][k]+b[k][j]); 记搜主体

冷静分析,每次搬n个盘子都有两种搬法:

方法一

CF392BTower of Hanoi(记忆化搜索)

方法二

CF392BTower of Hanoi(记忆化搜索)

我们知道每次最大盘的代价直接就是a[][],而其余n-1个是可以由递归记搜得到的

当递归到只剩一个盘时,只需要用预处理出的最优解b[][]即可

int dfs(int l,int r,int n){ if(f[l][r][n]) return f[l][r][n]; //已经走过,直接返回 if(n==1) return b[l][r]; //递归边界,只剩一个盘 int x=6-l-r; //表示中介盘,因为三个盘编号之和为6 int an1=dfs(l,x,n-1)+dfs(x,r,n-1)+a[l][r]; //方法一 int an2=(dfs(l,r,n-1)<<1)+dfs(r,l,n-1)+a[l][x]+a[x][r]; //方法二 return f[l][r][n]=min(an1,an2); //取个最优值 }

dfs(l,r,n)表示将n个盘从l移到r的方案数

所以答案就是dfs(1,3,n)

注意这题还会爆int

AC代码:

#include <bits/stdc++.h> #define int long long using namespace std; int n,a[5][5],b[5][5],f[5][5][50]; int dfs(int l,int r,int n){ if(f[l][r][n]) return f[l][r][n]; if(n==1) return b[l][r]; int x=6-l-r; int an1=dfs(l,x,n-1)+dfs(x,r,n-1)+a[l][r]; int an2=(dfs(l,r,n-1)<<1)+dfs(r,l,n-1)+a[l][x]+a[x][r]; return f[l][r][n]=min(an1,an2); } signed main(){ for(int i=1;i<=3;i++) for(int j=1;j<=3;j++) scanf("%lld",&a[i][j]),b[i][j]=a[i][j]; for(int i=1;i<=3;i++) for(int j=1;j<=3;j++) if(i!=j) for(int k=1;k<=3;k++) if(k!=i&&k!=j) b[i][j]=min(b[i][j],b[i][k]+b[k][j]); scanf("%lld",&n); printf("%lld",dfs(1,3,n)); }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpsyds.html