题目链接:http://ybt.ssoier.cn:8088/statusx.php?runidx=6901198
【题目描述】
在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放 k 个棋子的所有可行的摆放方案 C。
【输入】
输入含有多组测试数据。
每组数据的第一行是两个正整数n,k,用一个空格隔开,表示了将在一个n×n的矩阵内描述棋盘,以及摆放棋子的数目。 (n≤8,k≤n)
当为−1−1时表示输入结束。
随后的nn行描述了棋盘的形状:每行有n个字符,其中 ## 表示棋盘区域,.. 表示空白区域(数据保证不出现多余的空白行或者空白列)。
【输出】
对于每一组数据,给出一行输出,输出摆放的方案数目C(数据保证C<231)。
【输入样例】
2 1 #. .# 4 4 ...# ..#. .#.. #... -1 -1【输出样例】
2 1
解题思路:
1.本来以为和n皇后问题有点类似,想用类似的解法来写,但是发现行不通,n皇后里面每行放一个是固定的,但是这个题里面并没有说明每行必须放,而且放的总个数也小于等总行数,所以用那个方法就行不通了
2.这题正确的思路就是:定义一个数组来标记每一列是否放过棋子,在定义一个全局变量去存储已摆放的棋子数,从第一行开始搜索,如果能放棋子,那就棋子数加一,去搜索下一行,如果搜索的过程中棋子够了,那就说明一个摆放方法已经找到了。
3.这题最关键的地方就是等一行搜索玩完了(一般是在dfs里面写一个for循环),继续去搜下一行。
具体来看代码:
#include<iostream> #include<string.h> using namespace std; int n,k,book[10]; char a[10][10]; int way,sum;//已有几个棋子放好和可行方案 void dfs(int r)//第几行 { if(way==k) { sum++; return ; } if(r>=n) return ; for(int i=0;i<n;i++) { if(book[i]==0&&a[r][i]=='#') { book[i]=1; way++; dfs(r+1); way--; book[i]=0; } } dfs(r+1); } int main() { while(cin>>n>>k) { if(n==-1&&k==-1) break; memset(book,0,sizeof(book)); sum=0;way=0; for(int i=0;i<n;i++) for(int j=0;j<n;j++) cin>>a[i][j]; dfs(0); cout<<sum<<endl; } return 0; }