2038 - 汉诺塔
时间限制 : 1 秒
内存限制 : 128 MB
汉诺塔是根据一个传说形成的一个问题:
有三根杆子A,B,C。A杆上有N个(N>1)穿孔圆盘,盘的尺寸由下到上依次变小。要求按下列规则将所有圆盘移至C杆:
1.每次只能移动一个圆盘;
2.大盘不能叠在小盘上面。
提示:可将圆盘临时置于B杆,也可将从A杆移出的圆盘重新移回A杆,但都必须遵循上述两条规则。
问:如何移,最少要移动多少次?
MiaoWu玩三根杆子移动圆盘玩腻了。于是,它从寝室偷了m-3根杆子,想用这m根杆子来移动盘子,问n个盘子从起始盘移动到目标盘,至少需要移动多少步?
题目输入
输入m,n到文件末尾结束(3<=m<=20 , 0<=n<=1000)
题目输出
输出最小移动步数
输入/输出样例
输入格式
3 3 3 4 3 5 4 1 4 12
输出格式
7 15 31 1 81
C++解答
#include<stdio.h> #include<string.h> #include<ctime> #include<vector> #include<algorithm> using namespace std; #define N 1000000000 inline vector<int> change(int val) { vector<int>ans; while(val) { ans.push_back(val%N); val/=N; } return ans; } inline vector<int> equ(vector<int> a) { vector<int>ans; for(int i=0;i<a.size();i++) ans.push_back(a[i]); return ans; } inline vector<int> Min(vector<int> a,vector<int> b) { if(a.size()>b.size()) return b; else if(a.size()<b.size()) return a; else { for(int i=a.size()-1;i>=0;i--) { if(a[i]<b[i]) return a; else if(a[i]>b[i]) return b; } return a; } } inline vector<int> add(vector<int>a,vector<int>b) { vector<int>ans; int l1=a.size(),l2=b.size(),l=0; int m=0; while(l<min(l1,l2)) { int p=a[l]+b[l]+m; m=p/N; ans.push_back(p%N); l++; } while(l<l1) { int p=a[l]+m; m=p/N; ans.push_back(p%N); l++; } while(l<l2) { int p=b[l]+m; m=p/N; ans.push_back(p%N); l++; } if(m!=0) ans.push_back(m); return ans; } inline void Print(vector<int> a) { for(int i=a.size()-1;i>=0;i--) { printf("%d",a[i]); } printf("\n"); } vector<int>dp[21][1001]; inline void init() { for(int i=3;i<=20;i++) dp[i][1].push_back(1); for(int i=3;i<=20;i++) dp[i][2].push_back(3); for(int i=3;i<=1000;i++) { dp[3][i]=add(dp[3][1],add(dp[3][i-1],dp[3][i-1]));//dp[3][1]); } for(int i=4;i<=20;i++) for(int j=3;j<=1000;j++) { dp[i][j]=add(dp[i-1][1],add(dp[i][j-1],dp[i][j-1]));//,dp[i-1][1]); for(int k=2;k<=j;k++) { dp[i][j]=Min(dp[i][j],add(dp[i-1][k],add(dp[i][j-k],dp[i][j-k])));//dp[i-1][k])); } } } int main() { int m,n; init(); //printf("zz\n"); while(~scanf("%d%d",&m,&n)) { if(n==0) printf("0\n"); else Print(dp[m][n]); } }
Java解答
import java.math.BigDecimal; import java.math.BigInteger; import java.util.Scanner; public class Main { public static BigInteger min(BigInteger a,BigInteger b) { if(a.compareTo(b)<0) return a; return b; } public static void main(String args[]) { Scanner cin=new Scanner(System.in); int maxn=1100; BigInteger dp[][]=new BigInteger[21][maxn]; for(int i=0;i<maxn;i++) { dp[2][i]=BigInteger.ZERO; dp[3][i]=BigInteger.valueOf(2).pow(i).subtract(BigInteger.ONE); } dp[2][1]=BigInteger.ONE; for(int i=4;i<21;i++) { dp[i][0]=BigInteger.ZERO; for(int j=1;j<maxn;j++) { dp[i][j]=dp[i-1][j]; for(int k=0;k<=j;k++) dp[i][j]=min(dp[i][j],dp[i][j-k].multiply(BigInteger.valueOf(2)).add(dp[i-1][k])); } } while(cin.hasNext()) { int m=cin.nextInt(); int n=cin.nextInt(); System.out.println(dp[m][n]); } } }