《汉诺塔》进阶内容算法

夙愿已清 提交于 2020-02-13 22:03:45

哈喽,大家好,我是Tony:
欢迎大家访问我的个人主页:Tony’s Blog,让我们一起站在巨人的肩膀之上!
在这里插入图片描述
这篇博客将以《汉诺塔》为基础进行汉诺塔进阶:

编程题

给定一个整形数组arr,其中只含有1,2和3,代表所有圆盘目前的状态,1代表左柱,2代表中柱,3代表右柱,arr[i]的值代表第i+1个圆盘的位置。比如,arr=[3,3,2,1],代表第一个圆盘在右柱上、第2个圆盘在右柱上、第3个圆盘在中柱、第4个圆盘在左柱上。如果arr代表的状态是最优移动轨迹过程中出现的状态,返回arr这种状态是最优移动轨迹中的第几个状态。如果arr代表的状态不是最优移动轨迹过程中出现的状态,则返回-1.

举例

arr[1,1]。两个圆盘目前都在左柱上,也就是初始状态,所以返回0.

arr[2,1]。第一个圆盘在中柱上,第二个圆盘在左柱上,这个状态是2个圆盘的汉若塔游戏最优移动轨迹的第1步,所以返回1

arr[3,3]。第一个圆盘在右柱上,第2个圆盘在右柱山个,这个状态是2个圆盘的汉诺塔游戏中最优移动轨迹的第3步,所以返回3.

arr[2,2]。第一个圆盘在中柱上、第二个圆盘在中柱上,这个状态是2个圆盘的汉若塔游戏最优移动轨迹中不会出现的状态,所以返回-1.

说明

汉诺塔永远只有三步:

  • 把n-1的盘子移动到缓冲区
  • 把1号从起点移到终点
  • 把缓冲区的n-1号盘子移动到终点

因此算法是找到最大圆盘的位置arr[N-1]在哪个柱子上,根据这个来判断到了哪一步

整个过程可以总结为:

1、如果最大圆盘在左柱上,则继续递归1~(i-1)个盘子的情况,其目标是从left(左柱)到buffer(中柱)

2、如果最大圆盘在右柱上,起码走完了2^(i-1)步,则继续递归1~(i-1)个盘子的情况,其目标是从buffer(中柱)到right(右柱)

3、如果最大圆盘在中柱上,则直接返回-1

代码(递归)

#include "stdafx.h"
#include<iostream>
#include<vector>
#include<math.h>
using namespace std;
int process(vector<int>arr, int i, int left, int buffer, int right)
{
	int res = 0;
	if (i == -1)
	{
		return 0;
	}
	else if (arr[i] == buffer)
	{
		return -1;
	}
	else if (arr[i] == left)
	{
		return process(arr, i - 1, left,right ,buffer );
	}
	else 
	{
		
		res +=process(arr, i - 1, buffer, left, right);
		
	}
	return res+pow(2,i);
}
int funoi2(vector<int>arr)
{
	if (arr.size() == 0)
	{
		return -1;
	}
	int len=arr.size();
	return process(arr, len - 1, 1, 2, 3);
	
	
	int _tmain(int argc, _TCHAR* argv[])
{
	int i, j;
	int n = 3;
	vector<int>arr = {3,3};

	int res=funoi2(arr);
	cout << res;
	return 0;
}

代码(非递归)

// ConsoleApplication2.cpp : 定义控制台应用程序的入口点。
//汉诺塔进阶

#include "stdafx.h"
#include<iostream>
#include<vector>
#include<math.h>
using namespace std;

//非递归算法
int funoi2(vector<int>arr)
{
	if (arr.size() == 0)
	{
		return -1;
	}
	int left = 1;
	int buffer = 2;
	int right = 3;
	int len = arr.size() - 1;
	int res = 0;
	int temp = 0;
	while (len>=0)
	{
		if (arr[len] == buffer)
		{
			return -1;
		}
		if (arr[len] == left)
		{
			temp = buffer;
			buffer=right;
			right = temp;
			
		}
		else if (arr[len]==right)
		{
			res += pow(2,len);
			temp = left;
			left = buffer;
			buffer = temp;
			
		}
		
		len--;
	}
	return res;
}

int _tmain(int argc, _TCHAR* argv[])
{
	int i, j;
	int n = 3;
	vector<int>arr = {3,3};

	int res=funoi2(arr);
	cout << res;
	return 0;
}


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!