题目大意:3个桩的汉诺塔,每个数据给你一个n,表示盘子的个数,所有盘子起先都是在 A 上,给你一个列表,6个成对的字母,比如 AB 是表示把 A 顶上的盘子移动到 B 上,它整个流程是这样的:从头开始走那个表,找到第一个合法的移动(就是普通汉诺塔的规则一样,再加上后面的那个条件),然后就退出,又从头开始走第二遍表。这里还有另外一个条件,就是同一个盘子不能被连续的移动两次(in a row 原来是连续的意思,一直以为是同一行的意思,⊙﹏⊙b汗)。最后让你输出步数。
思路:设 d[ i ] 表示把 i 个盘子移好的步数, d[ i ] = x*d[ i - 1] + y ,x、y为未知变量,用模拟求出1个、2个、3个盘子移好需要的步数,然后列方程解出 x、y,d[ 1 ] = 1,最后一遍地推就好。
为什么就这样设两个未知量解出来就好了,也就是为什么它一定满足这个关系式,我也不知道,因为上面那个思路是我自己看一个大神的代码纯YY出来的。。= = 我只知道 如果是普通的汉诺塔 d[ i ] = 2*d[ i - 1] + 1,但是这道题目就这样设两个未知量 x、y搞搞就好了,真的想不明白,难道是类比YY?如果有哪位大神有幸光临的话,希望能不吝赐教,小弟不胜感激~~
代码如下(按照那个思路,模仿某大神写的):
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long lld;
typedef pair<int,int> PII;
#define MP make_pair
vector < PII > al;
int is_legel(vector <int> a,vector <int> b)
{
if(a.empty()) return 0;
if(b.empty() || a.back() < b.back())
return 1;
return 0;
}
int get_val(int k)
{
vector <int> p[3];
for(int i = k;i>=1;i--) p[0].push_back(i);
int step = 0;
int pl = -1;
while(p[1].size() != k && p[2].size() != k)
{
step ++;
for(int i = 0;i<al.size();i++)
{
int from = al[i].first,to = al[i].second;
if(is_legel(p[from],p[to]))
{
if(pl == p[from].back()) continue;
pl = p[from].back();
p[to].push_back(p[from].back());
p[from].pop_back();
break;
}
}
}
//printf("k = %d,step = %d\n",k,step);
return step;
}
int val[5];
char str[11];
int main()
{
int n;
while(~scanf("%d",&n))
{
al.clear();
for(int i = 0;i<6;i++)
{
scanf("%s",str);
al.push_back(MP(str[0]-'A',str[1]-'A'));
}
for(int i = 1;i<=3;i++)
val[i] = get_val(i);
int x = (val[3] - val[2])/(val[2] - val[1]);
int y = val[3] - val[2]*x;
lld ans = 1;
for(int i = 2;i<=n;i++)
ans = ans*x + y;
printf("%lld\n",ans);
}
return 0;
}