log P1242 新汉诺塔

传送门:https://www.luogu.org/problemnew/show/P1242


 

乍一看可能会被吓到,但仔细想想其实这题还是很水的

对比一下普通汉诺塔问题,新汉诺塔挪盘的策略不变,只是有个别地方不同:

1.各个盘并不集中在一个柱上,每个柱上都可能会有盘。

2.各个盘最终的目标不是挪到同一个柱上。

那么问题来了,这种情况下怎样挪才能达成目标并且保证走的是是步数最少的方案呢?

结合上述不同和移动盘的原则(小盘不能挪到大盘上面)可以得出适用于本题的移动原则

1.必须先挪大盘再挪小盘

2.挪大盘时,所有的小盘必须挪到一个中转柱上

所以,现在所有的问题归结于确定合适的中转柱上,而显然,中转柱既不能是出发点,也不能是目标点,因此可得出中转柱为6-出发点标号-目标点标号。

本题结束。

完整代码如下(柠檬评测是满分但是洛谷只给90emmm原因正在发掘中)

#include<iostream>
using namespace std;
int n;//圆盘总数
int m;//每个柱子上盘的个数
int x;//每个盘子的编号
int step=0;//计数器
int set[233],reach[233];//记录每个盘的出发点和目标点
const char item[]={'0','A','B','C'};
void ahaha(int x,int y)//x为盘子编号,y为目标点
{
if(set[x]==y) return;//出发点即为目标点,无需再移
for(int i=x-1;i>=1;i--)
ahaha(i,6-set[x]-y);//移走所有小盘到中转柱
cout<<"move "<<x<<" from "<<item[set[x]]<<" to "<<item[y]<<endl;//移动盘
step++;//不要忘了计数器
set[x]=y;//已归位,记录
}
int main()
{
cin>>n;
for(int i=1;i<=3;i++){
cin>>m;
for(int g=1;g<=m;g++)
{
cin>>x;
set[x]=i;//记录出发点
}
}
for(int i=1;i<=3;i++)
{
cin>>m;
for(int g=1;g<=m;g++)
{
cin>>x;
reach[x]=i;//记录目标点
}
}
for(int i=n;i>=1;i--)//从大到小挪
ahaha(i,reach[i]);//按顺序将每个盘子归位
cout<<step;//输出步数
return 0;

}

  


原文地址:https://www.cnblogs.com/charlesss/p/10093145.html