本题的关键是应用IDA*算法,降低时间复杂度,启发函数的发现和推导是重点。
对于可以用回溯法求解但解答树的深度没有明显上限的题目,可以考虑使用迭代加深搜索。设计一个乐观估计函数,预测从当前节点至少还学要扩展几层才有可能得到解,则状态空间搜索变成了IDA*算法。
刚开始吧状态定义为typedef int State[12],但后来发现编译器老是报错并且极易出现各种错误,索性直接定义为一个struct。
#include <bits/stdc++.h> using namespace std; struct State{ int a[12]; }; int n, kase = 0, maxd; int getH(State cur) { int cnt = 0; for(int i = 0; i < n-1; ++i) if(cur.a[i]+1 != cur.a[i+1]) cnt++; return cnt; } bool DFS(int d, State u) { int H = getH(u); if(d == maxd) return H == 0; if(3*d + H > 3*maxd) return false; for(int x = 0; x < n - 1; ++x) for(int l = 1; l <= x+1; ++l) for(int r = 1; r <= n-x-1; ++r){ State v; memcpy(v.a, u.a, sizeof(u.a)); for(int i = x - l + 1, j = x + r - l + 1; i <= x; ++i, ++j) v.a[j] = u.a[i]; for(int i = x + 1, j = x - l + 1; i <= x + r; ++i, ++j) v.a[j] = u.a[i]; if(DFS(d + 1, v)) return true; } return false; } int main() { ios::sync_with_stdio(false); while(cin >> n && n){ State beg; for(int i = 0; i < n; ++i) cin >> beg.a[i]; for(maxd = 0; ; ++maxd) if(DFS(0, beg)) break; printf("Case %d: %d ", ++kase, maxd); } return 0; }