M - 卿学姐失恋了Ⅱ
给你一个合法的汉诺塔状态,问你能否在M秒之内把他们都放到一根柱子上,圆盘总数是20
首先我们可以知道,我们最后要放到的那根柱子一定是0号盘子,就是最大的盘子,所在的柱子,为什么这样呢,因为不这样的话,我们就要移动0号盘子,我们想移动0号盘子,那么其他所有的盘子都必须移到某一根柱子上,这时我们可以把0号盘子移到另一根柱子上,然后再把其他所有的盘子移到0号盘子所在的柱子上,这样显然是不如把所有盘子移到0号盘子上所花时间短的(具体证明的话,我们可以假设移动每个盘子都花的时间是最长的时间,就是它上面全都叠满了盘子的情况,然后发现把这些时间总和加起来,才是之前那个的第二步,就是把其他所有盘子移到0号盘子所在的新位置),所以肯定不如固定0号盘子
现在我们知道了最终状态后,可以考虑最终状态往初始状态推的最少步数,这个比较好考虑
首先,0号肯定是不用动的,然后这个时候所以的盘子都在0号上,我们找到最大的不应该在这根柱子上的盘子,我们要把它移到它的目标柱子,这个过程的最短步数,就是把它移到目标柱子,这时所以比它小的盘子在另外一根柱子上,然后我们继续从大向小的检查盘子是否在所该在的柱子上,然后模拟移动情况,记录时间就行
最后把总时间和M做个比较就可以啦
代码:
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <set>
using namespace std;
#define ll long long
int a[12], pow_2[22], sta[4][22];
int pos_other(int a, int b)
{
if (a == 1)
{
if (b == 2)
return 3;
else if (b == 3)
return 2;
}
if (a == 2)
{
if (b == 1)
return 3;
else if (b == 3)
return 1;
}
if (a == 3)
{
if (b == 2)
return 1;
else if (b == 1)
return 2;
}
return 0;
}
int hanoi(int num, int pos, int aim)
{
int pos1 = pos_other(pos, aim);
for (int i = 0; i < 22; ++i)
{
if (sta[pos][i] == num)
{
for (int j = 0; j < 22; ++j)
{
if (sta[pos][i + j] != 0)
sta[pos][i + j] = 0;
else
break;
}
for (int j = 0; j < 22; ++j)
{
if (sta[pos1][j] == 0)
{
for (int k = num + 1; k <= 20; ++k)
sta[pos1][j + k - num - 1] = k;
break;
}
}
break;
}
}
for (int i = 0; i < 22; ++i)
{
if (sta[aim][i] == 0)
{
sta[aim][i] = pos;
break;
}
}
return pow_2[20 - num];
}
int main()
{
//freopen("input.txt", "r", stdin);
pow_2[0] = 1;
for (int i = 1; i <= 21; ++i)
pow_2[i] = pow_2[i - 1] << 1;
int t, ans = 0;
scanf("%d", &t);
for (int i = 1; i <= 20; ++i)
scanf("%d", &a[i]);
int pos = a[1];
for (int i = 1; i <= 20; ++i)
sta[pos][i - 1] = i;
for (int i = 2; i <= 19; ++i)
{
if (pos == a[i])
continue;
ans += hanoi(i, pos, a[i]);
//printf("%d %d\n", i, ans);
pos = pos_other(pos, a[i]);
}
if (a[20] != pos)
{
for (int i = 22; i >= 0; --i)
if (sta[pos][i] == 20)
{
sta[pos][i] = 0;
break;
}
for (int i = 0; i < 22; ++i)
if (sta[a[20]][i] == 0)
{
sta[a[20]][i] = 20;
break;
}
++ans;
}
//printf("%d\n", ans);
if (ans > t)
printf("NO\n");
else
printf("YES\n");
//system("pause");
//while (1);
return 0;
}