题目链接:传送门
题目大意:
汉诺塔,给定n个盘子(n <= 45),起始状态和结束状态,求最小的步数以及路径。
思路:
考虑用dfs贪心地将剩余最大盘归位。
#include<bits/stdc++.h> using namespace std; const int MAX_N = 50; const int SUM = 3; int N, ans; int f1[MAX_N], f2[MAX_N]; void dfs(int cur, int st, int ed, bool now) { int mid = SUM - st - ed; if (st == ed) { if (cur > 1) dfs(cur-1, f1[cur-1], now ? f2[cur-1] : ed, now); return; } if (cur > 1) dfs(cur-1, f1[cur-1], mid, false); ans++; printf("move %d from %c to %c ", cur, 'A' + st, 'A' + ed); f1[cur] = ed; if (cur > 1) dfs(cur-1, f1[cur-1], now ? f2[cur-1] : ed, now); } void input() { ans = 0; cin >> N; for (int i = 0; i < 6; i++) { int x; cin >> x; while (x--) { int cur; cin >> cur; if (i/3) f2[cur] = i%3; else f1[cur] = i%3; } } } int main(){ input(); dfs(N, f1[N], f2[N], true); cout << ans << endl; return 0; }
以上代码会被这组数据hack。
/* 3 1 3 0 2 2 1 2 2 1 0 1 3 */
但是大多数情况下贪心思路没有问题,所以用模拟退火优化。
#include<bits/stdc++.h> using namespace std; const int INF = 0x3f3f3f3f; const int MAX_N = 50; const int SUM = 3; int N, ans, icur; string sans, scur; int ff1[MAX_N], ff2[MAX_N]; int f1[MAX_N], f2[MAX_N]; void mov(int cur, int st, int ed) { icur++; scur += "move "; if (cur >= 10) scur += char(cur/10 + '0'); scur += char(cur%10 + '0'); scur += " from "; scur += char(st + 'A'); scur += " to "; scur += char(ed + 'A'); scur += " "; } void dfs(int cur, int st, int ed, bool now) { int mid = SUM - st - ed; if (st == ed) { if (cur > 1) dfs(cur-1, f1[cur-1], now ? f2[cur-1] : ed, now); return; } if (cur > 1) dfs(cur-1, f1[cur-1], mid, false); mov(cur, st, ed); f1[cur] = ed; if (cur > 1) dfs(cur-1, f1[cur-1], now ? f2[cur-1] : ed, now); } void input() { ans = INF; cin >> N; for (int i = 0; i < 6; i++) { int x; cin >> x; while (x--) { int cur; cin >> cur; if (i/3) ff2[cur] = i%3; else ff1[cur] = i%3; } } } int main(){ input(); int T = 100; srand(44356542); while (T--) { icur = 0; scur = ""; for (int i = 1; i <= N; i++) { f1[i] = ff1[i]; f2[i] = ff2[i]; } for (int i = N; i >= 1; i--) { if (rand()%(i+1) != 0) dfs(i, f1[i], f2[i], true); else dfs(i, f1[i], SUM-f1[i]-f2[i], true); } dfs(N, f1[N], f2[N], true); if (ans > icur) { ans = icur; sans = scur; } } cout << sans << ans << endl; return 0; } /* 3 1 3 0 2 2 1 2 2 1 0 1 3 */