单柱汉诺塔翻转问题

在一个塔座上有一叠大小不等的共n 个圆盘。各圆盘从小到大编号为1,2,……,n。
初始时,这些圆盘自下而上散乱地叠在一起。现要求按照以下翻转规则,经若干次翻转,将
塔座上的这一叠圆盘排好序,即按自底向上,从大到小的顺序叠置。 
翻转规则:每次可以将最顶上的若干圆盘翻转,即按其相反的次序叠置。 
例如,在下面的 3个圆盘叠置状态中,中间状态是在左边状态中第3 个圆盘以上所有圆
盘翻转后得到的,相应翻转记为flip(3);右边状态是将中间状态中第1个圆盘以上所有圆
盘翻转得到的,相应翻转记为flip(1)。 
8  7  2 
4  6  5 
6  4  8 
7  8  4 
5  5  6 
2  2  7 
 
´实验任务: 
对于给定的大小不等的n个圆盘的初始状态,用翻转运算将n 个圆盘排序。 
´数据输入: 
由文件input.txt给出输入数据。第 1 行是给定的圆盘自顶向下的初始状态。 
´结果输出: 
将排序所用的翻转运算依次输出到文件 output.txt。输出翻转运算flip(i)时,只要输出数
字i即可,相邻数字用空格分隔。 
输入文件示例  输出文件示例 
input.txt  output.txt 
5 1 2 3 4  1 2 

简单起见我就以0作为输入结束。这个算法的思想和朴素汉诺塔还是有点像的,朴素汉诺塔的思想是先将(n-1)块圆盘从A->B,然后将最大的那块从A->C,再把这(n-1)块从B->C,当然这(n-1)块不可能一次性移动,这就需要递归了

#include <cstdio>  

int cnt = 0;

void Hanoi(int n = 5, char A = 'A', char B = 'B', char C = 'C')
{
	if( n == 1 ){
		printf("%c->%c\n", A, C);
		cnt++;
	}else{
		Hanoi(n-1, A, C, B);	//(n-1)块A->B
		Hanoi(1, A, B, C);	// 1块A->C
		Hanoi(n-1, B, A, C);	//(n-1)块B->C 
	}		
} 
 
int main()  
{  
	Hanoi();
	printf("cnt = %d\n", cnt);
        return 0;  
} 

而这个翻转汉诺塔问题的思想就是,在塔(数组或者容器)中找到最大圆盘(值),想办法将其翻转至相对最下方。因为塔只能将上方的圆盘翻转,因此需要将该圆盘先翻转至最高处,再从最高处翻转至相对最低处(之所以说相对是因为随着翻转进行比这个值更大的已经在塔底了

#include <iostream>
#include <vector>
#include <cstdio>
using namespace std;

vector<int> data;

void init_Data()
{
	int x;
	vector<int>().swap(data);
	//	以0代表结束 
	while( scanf("%d",&x) && x!=0 )
		data.push_back(x);	
}

bool isOver()
{
	for(int i = 1; i < data.size(); ++i)
		if( data[i] < data[i-1] )
			return false;
	return true;
}

void reverse(int m, int n)
{
	int t;
	while( m < n ){
		t = data[m];
		data[m] = data[n];
		data[n] = t;
		++m, --n;
	} 	
}

void reverse_Hanoi()
{
	int max, maxIndex, pos = 0;
	int n = data.size(), size = data.size();
	while( n-- )
	{
		//	判断是否结束 
		if( isOver() )
			return;
		maxIndex = 0, max = data[0];
		//	找到相对最大值 
		for(int i = 0; i < size-pos; ++i)
			if( data[i] > max ){
				max = data[i];
				maxIndex = i;
			}
		//	若相对最大值在相对最底部,无需操作,否则	
		if( maxIndex != size-pos-1 ){
                        //      若相对最大值已经在最高层,无需翻转 
			if( maxIndex != 0 ){
                        //	否则先将相对最大值翻转到最高层
				reverse(0, maxIndex);
				printf("%d ", size-maxIndex);
			}
			//	再将相对最大值翻转到相对最底部 
			reverse(0, size-pos-1);
			printf("%d ", pos+1);	
		}	
		pos++;
	}			
} 

int main()
{
	init_Data();
	reverse_Hanoi();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Love_Irelia97/article/details/82556421
今日推荐