2016 UESTC Training for Data Structures M - 卿学姐失恋了Ⅱ CDOJ 1350 汉诺塔 模拟

来源:互联网 发布:linux的网络配置文件 编辑:程序博客网 时间:2024/05/05 08:30

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 longint 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;elsebreak;}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");elseprintf("YES\n");//system("pause");//while (1);return 0;}

1 0
原创粉丝点击