P1219 [USACO1.5]八皇后 Checker Challenge
好像是紫书上面的题目,没有想象的那么难.
标记的思想.
n最大才13,可以深搜,但是搜的过程中就得把不可能情况排除掉,不然搜一年(虚指).
#include <algorithm> #include <cstdio> #include <cstring> #include <iostream> using namespace std; int n, ct, s[20]; bool used[20]; void dfs(int pos) { if (pos != n) { for (int i = 1; i <= n; i++) if (!used[i]) { bool bad = false; for(int j = 0; j < pos; j++) if(s[j] + j == pos + i || s[j] - j == i - pos) { bad = true; break; } if(bad) continue; used[i] = true; s[pos] = i; dfs(pos + 1); used[i] = false; } } else { ct++; if (ct <= 3) { for (int i = 0; i < n; i++) printf("%d ", s[i]); putchar(' '); } } } int main() { cin >> n; dfs(0); cout << ct << endl; return 0; }
这样就过了,但是剪枝效率太低了,险些超时.
更好的策略是每放置一枚棋子,将该棋子所在的对角线的"特征值"s[pos] + pos标记为已用,检查下一颗棋子的时候就可以很快排除非法的位置了.