Description
Input
Output
Sample Input
2 1 #. .# 4 4 ...# ..#. .#.. #... -1 -1
Sample Output
2 1
做这道题之前,最好了解一下经典的深搜回溯问题---八皇后问题,这道题和八皇后唯一的区别就是八皇后在每一行都需要放置一个皇后,而这道是不确定的,有些行可能放,也可能不放,只要最终放够k个就行,因此,就只多了对于搜索了这一行以后的这一行放于不放的问题。也就是在搜素中计数器加 1 与 不加 1 的区别,我在搜素的时候是在棋盘每一行的尾部加了一个能放置棋子的位置,如果棋子放到的是这一行的最尾部,则就认为是不在这一行放,计数器不加 1 反之,加 1, 其实这道题不用每行加一个位置那么费事,就是在该行搜完以后加一个不放置的搜索就行,下面我把两种代码都附上
附上代码:(每行加一个位置的)
#include <iostream> #include <cstring> #include <algorithm> #include <queue> #include <stack> #include <cstdio> using namespace std; char Map[15][15]; int n,k,ans; int visit[10]; 标记在 i 列是否有棋子 void dfs(int cur,int num) // cur 表示当前行 num 表示已经放了几个棋子 { if(num > k || cur > n) // 如果放置棋子数已经够了 或者 搜出棋盘外就返回 return; if(num == k) // 搜到结果后答案数就 加 1; { ans++; return; } else { for(int i = 0;i <= n;i++) { if(Map[cur][i] == '#' && !visit[i]) { if(i != n) // 判断时否为该行的最尾部 { visit[i] = 1; dfs(cur + 1,num + 1); visit[i] = 0; } else { dfs(cur + 1,num); } } } } } int main() { while(cin >> n >> k) { ans = 0; memset(visit,0,sizeof(visit)); memset(Map,0,sizeof(Map)); if(n == -1 && k == -1) break; for(int i = 0;i < n;i++) { scanf("%s",Map[i]); Map[i][n] = '#'; // 在每行末尾加上一个位置 } dfs(0,0); cout << ans << endl; } return 0; }
附上代码:(不加多余的位置,直接搜)
#include <iostream> #include <cstring> #include <algorithm> #include <queue> #include <stack> #include <cstdio> using namespace std; char Map[15][15]; int n,k,ans; int visit[10]; void dfs(int cur,int num) { if(num > k || cur > n) return; if(num == k) { ans++; return; } else { for(int i = 0;i < n;i++) { if(Map[cur][i] == '#' && !visit[i]) { visit[i] = 1; dfs(cur + 1,num + 1); visit[i] = 0; } } dfs(cur + 1,num); // 在每一行n个位置搜完后,再搜一个该行不放置的方法 } } int main() { while(cin >> n >> k) { ans = 0; memset(visit,0,sizeof(visit)); memset(Map,0,sizeof(Map)); if(n == -1 && k == -1) break; for(int i = 0;i < n;i++) { scanf("%s",Map[i]); } dfs(0,0); cout << ans << endl; } return 0; }