在一個給定形狀的棋盤(形狀可能是不規則的)上面擺放棋子,棋子沒有區別。要求擺放時任意的兩個棋子不能放在棋盤中的同一行或者同一列,請編程求解對於給定形狀和大小的棋盤,擺放k個棋子的所有可行的擺放方案C。
Input
輸入含有多組測試數據。
每組數據的第一行是兩個正整數,n k,用一個空格隔開,表示了將在一個n*n的矩陣內描述棋盤,以及擺放棋子的數目。 n <= 8 , k <= n
當爲-1 -1時表示輸入結束。
隨後的n行描述了棋盤的形狀:每行有n個字符,其中 # 表示棋盤區域, . 表示空白區域(數據保證不出現多餘的空白行或者空白列)。
Output
對於每一組數據,給出一行輸出,輸出擺放的方案數目C (數據保證C<2^31)。
Sample Input
2 1
#.
.#
4 4
...#
..#.
.#..
#...
-1 -1
Sample Output
2
1
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
char a[10][10]; //記錄棋盤位置
int book[10]; //記錄一列是否已經放過棋子,放過則記爲1.沒放過記爲0
int n,k;
int total,m; //total 是放棋子的方案數 ,m是已放入棋盤的棋子數目
void DFS(int cur)
{
if(k==m)//以放入的棋子數等於棋子總數
{
total++;//方案+1
return ;
}
if(cur>=n) //邊界
return ;
for(int j=0; j<n; j++)
if(!book[j] && a[cur][j]=='#') //判斷條件book[j]就是第J列爲0時然後並且cur行j列是棋盤
{
book[j]=1; //則標記一下 這一列放一個
m++; // 放的棋子數+1
DFS(cur+1); //繼續判斷下一行
book[j]=0; //改回來能夠下一次的判斷
m--; //放過的棋子-1
}
DFS(cur+1); //到下一行
}
int main()
{
int i,j;
while(scanf("%d%d",&n,&k)&&n!=-1&&k!=-1) //限制條件
{
total=0;
m=0;
for(i=0; i<n; i++)
for(j=0;j<n;j++)
cin>>a[i][j];
memset(book,0,sizeof(book));
DFS(0);
printf("%d\n",total);
}
return 0;
}
看了一天才看懂,
我理解的DFS就是一條路走到黑,直到撞到南牆纔回頭,
然後下面我來用我自己的語言來解釋一下這道題
看圖
先輸入這個二維數組
。 #。#
。# # #
# # 。#
# # # 。
然後#的地方是可以放棋子的,然後開始放用深度DFS搜索先確定第一行的第一個能放棋子的那一列之後標記一下這一列
然後放棋子,進行遞歸(進入下一行重複操作還是下一行從第一列判斷是否有標記,然後有沒有#是否可以放棋子),像這一題
就是第一行放的2,第二行放的3,然後第三行放的1,然後第四行沒法放,執行最後的DFS(cur+1),return返回上一層
也就是第三行,然後第三行放到第4個,然後遞歸進入第4行,放第一個,然後成功棋子數=放入棋子數方案+1,
return上一層(也就是第3層,發現第三層沒有了,),執行最後的DFS然後返回上一層(第二層),然後第二層放到4
執行DFS,第3層放到1,然後DFS第四層放到3,然後執行最後的DFS,然後成功棋子數=放入棋子數方案+1,之後返回第4層
清空,然後循環判斷沒有可以放旗子的位置,然後執行最後的DFS進入第5層,越界然後返回第四層再返回第3層,發現也沒有位置可以放,之後繼續返回到第2層然後循環到第4列之後DFS。。。。。之後return,return到第一層,然後第一層第4繼續做遍歷
直到做完停止。