在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放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继续做遍历
直到做完停止。