棋盤問題
阿新 • • 發佈:2020-07-22
棋盤問題
(這麼簡單的板子題都能卡,太弱了md)
一開始用的複雜度能高到\(O(n!)\)的DFS...後面參考了一下題解,算是懂問題出在哪了。
那個\(O(n!)\)的方法是這樣想的,整個遍歷一遍棋盤,找到適合的就做標記,回溯...我自己看著是沒什麼問題,不過最後答案就是標答的\(k!\)倍...重複計算太多了
看了一下題解,問題在這:不是遍歷整個棋盤,而是遍歷到下一行。因為棋子不能放於同一列,這一列放完了就在下一列DFS,因此不會有重複的情況。
接下來的程式碼用的是從上到下的DFS,按理論來說,從左到右,從下到上應該都行吧。
//#include <bits/stdc++.h> #include <cstring> #include <iostream> using namespace std; typedef long long ll; typedef unsigned long long ull; int mod = 9973; const int INF = 0x3f3f3f3; const int maxn = 2e2 + 10; int n, k; char Map[10][10]; int xx[10], yy[10]; ll res = 0; void dfs(int y, int num) { if (num == 0) //棋子放完,答案+1 { res++; return; } for (int i = y; i < n; i++) //就是這樣,從y開始,而不是0 { for (int j = 0; j < n; j++) { if (Map[i][j] == '#' && (!xx[j]))//xx是記錄列是否有重複情況的 { xx[j] = 1; dfs(i + 1, num - 1);//DFS下一行,棋子少一個 xx[j] = 0;//回溯 } } } } int main() { while (cin >> n >> k) { res = 0; memset(xx, 0, sizeof(xx)); if (n == -1) break; for (int i = 0; i < n; i++) { cin >> Map[i]; } dfs(0, k); //從第0行開始,一開始有k個棋子要放 cout << res << endl; } return 0; }