1. 程式人生 > >漢諾塔計數 實現輸出64個圓盤移動多少次 java程式碼

漢諾塔計數 實現輸出64個圓盤移動多少次 java程式碼

因為漢羅塔的個數如果為1,2,3,4;那麼對應的移動次數為1,3,7,15相當於2^n-1,也可以說是上一次的結果乘以2加上1就是下一次的結果
由於當漢羅塔多了之後後面的數字會很大,有可能java的型別無法支援如此大的數,也為了可以快速高效的計算出結果,此時就不能用一般的方法統計,這裡我採用的是通過陣列的方式實現疊加統計
例如:a[] = {0,0,1,4}表示4位數,結果是14 如果要當其中某一位出現大於10的就向前一位進1,例如{0,2,23,11,3}得出的結果實際上應該是{0,4,4,1,3}:4413
如果這個數需要乘以一個數那麼就和每一位上的相乘最後進位,例如:{0,6,2}*2={0,12,4}={1,2,4}=124這樣的道理
最後用一個字串來得出最後的結果數字就可以了
下面的程式a[]表示用於統計的結果,是一個字串陣列,b[]表示上一個的結果陣列,c[]表示乘以2減去1後的結果陣列
public class 漢羅塔計數 {
	// N為多少個圓盤
	public static int N = 64;//這裡可以自己修改

	/**
	 * 處理結果
	 * @param a 得到的每一次運算的結果陣列
	 * @param c 得到當前移動的次數的陣列(也就是上一次的結果)
	 * @param n 遞迴次數的變數
	 */
	public static void processResult(String a[], int c[], int n) {
		//首先判斷遞迴次數是否小於制定的漢羅塔的個數-1(n從0開始的)
		if (n < N - 1) {
			for (int i = 0; i < N; i++) {
				if (c[i] == 0) {//如果前面為0表示不是第一位:例如0014=14,不需要0
					continue;
				} else {
					//取出這個數字放入a中
					for (int j = i; j < N; j++) {
						a[n + 1] += String.valueOf(c[j]);
					}
					break;
				}
			}
			//如果是最後一次計數,則輸出結果,直接結束方法
			if (n == a.length - 2) {
				System.out.println("總共" + N + "個圓盤共移動了:" + a[n + 1] + "次");
				return;
			}
			//繼續遞迴
			processResult(a, getLastResult(a, c, n + 1), n + 1);
		}
	}
	
	/**
	 * 獲取上一個結果
	 * @param a
	 * @param c
	 * @param n
	 * @return
	 */
	public static int[] getLastResult(String a[], int c[], int n) {
		//b用於獲取上一次的結果
		int b[] = new int[N];
		//先把字串轉變為一個個字元然後放入陣列中
		char[] t = a[n].toCharArray();
		for (int i = 0; i < t.length; i++) {
			b[t.length - 1 - i] = t[i] - '0';
		}
		//每個數字乘以2再放入c[]中
		for (int i = 0; i < t.length; i++) {
			c[N - 1 - i] = b[i] * 2;
		}
		c[N - 1]++;//加1
		//進行進位處理
		for (int i = N - 1; i > 0; i--) {
			if (c[i] >= 10) {
				c[i - 1] += c[i] / 10;
				c[i] %= 10;
			}
		}
		return c;
	}

	public static void main(String[] args) {
		//初始化a
		String a[] = new String[N];
		if (N == 1) {
			System.out.println("總共1個圓盤共移動了:1次");
		} else {
			for (int i = 0; i < a.length; i++) {
				a[i] = "";
			}
			int c[] = new int[N];
			a[0] = "1";//如果不是一個圓盤,那麼a[0]的結果是1
			//開始處理結果
			processResult(a, getLastResult(a, c, 0), 0);
		}
	}
}

最後結果:總共64個圓盤共移動了:18446744073709551615次