# Recursion# Math# Bit Manipulation

h664 - 河內塔 (Hanoi)

🔗 前往 ZeroJudge 原題

題目描述

題目要求在河內塔遊戲中,給定圓盤數量 N 和步數 S,輸出第 S 步移動的圓盤編號。梅林會以最佳方式移動圓盤,直到詢問提示。

解題思路

這題的核心在於理解河內塔移動的模式。在最佳策略下,河內塔的移動步驟可以被編號。題目給定的步數 S 實際上是按照最佳策略移動的第 S 步。程式碼利用了位運算和遞迴來計算在第 S 步應該移動哪個圓盤。fd(x, y) 函數的作用是找到在 x 個圓盤的河內塔中,第 y 步移動的圓盤編號。它通過遞迴地將步數 y 分解為更小的子問題來實現。a[i] 陣列預先計算了 2 的冪,用於快速計算步數範圍。

複雜度分析

  • 時間複雜度: O(N)
  • 空間複雜度: O(N)

程式碼

#include <iostream>
using namespace std;
int a[16]={0,1},t,n,m;
int fd(int x,int y){
	if(x==1)return 1;
	int x2=(1<<(x-1));
	if(y==x2)return x;
	else if(y>x2){
		return fd(x-1,y-x2);
	}
	else{
		return fd(x-1,y);
	}
}
int main(){
	cin.tie(0); ios::sync_with_stdio(0);
	for(int i=2;i<=15;++i)
		a[i]=a[i-1]*2+1;
	cin >> t;
	while(t--){
		cin >> n >> m;
		cout << fd(n,m) << "\n";
	}
}

Discussion