Strange Towers of Hanoi(奇怪的汉诺塔)

题目

题目

做法

没错,仍然是做法1和做法2

做法1

暴力出奇迹!!!!

我们发现这道题目是四个塔,那我们就四进制表示每个盘子的状态,大概是 2 24 2^{24} 224级别的,用bool数组不会爆炸,然后暴力模拟即可。

等会,好像是要最小步数,那我们用BFS而且bool改int就可以了,这么简单。

BFS开个队列,刚好用得上 i n t int int表示状态,空间多大?

64MB。。。。。

没错,这个做法是错的,空间卡住了动不了,时间是: O ( 2 24 ∗ 12 ) O(2^{24}*12) O(22412),也会炸,但是因为每个柱子是单调的,所以实践中会比这个小,但是空间已经炸了,就不尝试了。

做法2

递推。

我们想想,如果三个柱子的汉罗塔怎么做。

很容易知道,对于两个盘子以上的数量,我们要能移动这些盘子需要至少三根柱子,只有一个盘子移动时只需要两根柱子,因此对于 k k k个盘子而言,我们要利用三根柱子先把 k − 1 k-1 k1个盘子移动到第二根柱子,然后利用两根柱子把第 k k k个盘子放到第 3 3 3跟,再把 k − 1 k-1 k1个盘子利用三根柱子移动到第 3 3 3根,归纳一下就是: f ( i ) = f ( i − 1 ) ∗ 2 + 1 f(i)=f(i-1)*2+1 f(i)=f(i1)2+1

那么对于四根柱子而言,对于 k k k个盘子,由于 2 2 2个以上的盘子需要 3 3 3根柱子,所以我们虽然可以提前把 i i i个盘子放到一个柱子上减少移动压力,但是也最多只能放到一根柱子上。

所以递推式就出来了: f 4 ( n ) = f 4 ( n − i ) + f ( i ) f_4(n)=f_4(n-i)+f(i) f4(n)=f4(ni)+f(i)

#include<cstdio>
#include<cstring>
#include<cstdlib>
#define  N  14
using  namespace  std;
int  f3[N],f4[N];
inline  int  mymin(int  x,int  y){
    
    return  x<y?x:y;}
int  main()
{
    
    
	f3[1]=1;for(int  i=2;i<=12;i++)f3[i]=f3[i-1]*2+1,f4[i]=999999999;
	f4[1]=1;
	for(int  i=2;i<=12;i++)
	{
    
    
		for(int  j=0;j<i;j++)
		{
    
    
			f4[i]=mymin(f4[j]*2+f3[i-j],f4[i]);
		}
	}
	for(int  i=1;i<=12;i++)printf("%d\n",f4[i]);
	return  0;
} 

猜你喜欢

转载自blog.csdn.net/zhangjianjunab/article/details/107637745