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; }