*description:漢諾塔問題
* n代表漢諾塔遊戲中從小到小到大放置的的n個盤子,
* 開始時,所有盤子都放置在左邊的柱子上,按遊戲要求將其全部移動至右邊,
* 打印最優移動軌跡。
* n個盤子共需要移動2^i-1次
****************************************************************************************/
#include<iostream>
#include<vector>
#include<string>
using namespace std;
//方法:
// step1:把圓盤1~(n-1)從from移動到mid
// step2:把圓盤n從from移動到to
// step3:把圓盤1~(n-1)從mid移動到to
void process_1(int n, string from, string mid, string to)
{
if (n == 1)
cout << from << " ---> " << to << endl;
else
{
process_1(n-1, from, to, mid);
process_1(1, from, mid, to);
process_1(n-1, mid, from, to);
}
}
void printTrack(int n)
{
if (n == 0)
return;
process_1(3, "left", "mid", "right");
}
int main_06_1()
{
printTrack(3);
return 0;
}
/*****************************************************************
*description:漢諾塔進階問題
* 給定數組arr,只含1、2、3,代表圓盤狀態,如arr[i]=1,表示i圓盤在左柱
* 如果arr是漢諾塔最優軌跡上的狀態,則返回是第幾個狀態,否則返回-1
*****************************************************************/
//方法1:時間複雜度O(N),空間複雜度O(N)
// 對圓盤1~i來說,目標爲從from到to,分三種情況:
// 1.圓盤i在from上,不能判定步驟1是否完成,需進一步考慮1~(i-1)的情況,目標爲from到mid
// 2.圓盤i在to上,步驟1和2已經完成,已完成2^(i-1)步,再考慮1~(i-1),目標從mid到to
// 3.圓盤i在mid上,最優軌跡不存在這種情況,返回-1
int process_2(vector<int> arr, int i, int from, int mid, int to)
{
if (i == -1)
return 0;
if (arr[i] != from && arr[i] != to)
return -1;
if (arr[i] == from)
return process_2(arr, i-1, from, to, mid);
else
{
int rest = process_2(arr, i-1, mid, from, to);
if (rest == -1)
return -1;
return (1 << i) + rest;
}
}
int HanoState_1(vector<int> arr)
{
if (arr.size() == 0)
return -1;
return process_2(arr, arr.size()-1, 1, 2, 3);
}
//方法2:時間複雜度O(N),空間複雜度O(1)
//方法1改寫爲非遞歸形式。
int HanoState_2(vector<int> arr)
{
if (arr.size() == 0)
return -1;
int from = 1;
int mid = 2;
int to = 3;
int i = arr.size() - 1;
int res = 0;
int tmp = 0;
while(i >= 0)
{
if (arr[i] != from && arr[i] != to)
return -1;
if (arr[i] == to)
{
res += 1 << i;
tmp = from;
from = mid;
}
else
{
tmp = to;
to = mid;
}
mid = tmp;
i--;
}
return res;
}
int main_06_2()
{
vector<int> arr;
arr.push_back(2);
arr.push_back(1);
cout << HanoState_2(arr);
return 0;
}