题目网址:http://acm.pku.edu.cn/JudgeOnline/problem?id=1321
其实就是个神搜的题目,以前做过,但是在拿到题的时候还是会感觉有点我从下手,所以还是多做点就好了吧
具体思路:
棋盘问题, 棋子摆放的位置只能是#, 且不能同行和同列. 由于我采用的是按行递增的顺序来搜索的, 因此不可能出现同行的情况, 对于同列的情况, 我设置了一个变量col[], 来保存列的访问状态, 对于之前访问过的列, 棋子是不能再放在这一列上的.
dfs(begin, num) 代表将第k-num棵棋子放在begin行上, 然后就剩下num-1棵棋子需要放在begin行下面. 当然, 可能存在第num棵棋子根本无法放在begin行上的情况, 对于这种情况, dfs就回溯到上一个dfs调用的地方, 重新开始, 而如果遇到num=1, 且第begin行的一些列可以放的话, 就将方案数相应增加.
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
char ch[10][10];
int visit[10],sum,n;//visit为列的访问状态
void dfs(int begin,int x)
{
for(int j=0;j<n;j++)
if(ch[begin][j]=='#'&&visit[j]==0)
if(x==1)
sum++;
else
{
visit[j]=1;
for(int w=begin+1;w<=n-(x-1);w++){//条件w<n-(n-1),这是因为如果在比这个大了就一定不成立了,因为之后一行之多一个,从该地址遍历到结束也不会满足x个了
dfs(w,x-1);
}
visit[j]=0;
}
}
int main()
{
int x;
while(~scanf("%d%d",&n,&x)&&!(n==-1&&x==-1))
{
sum=0;
for(int i=0;i<n;i++)
scanf("%s",ch[i]);
memset(visit,0,sizeof(visit));
for(int i=0;i<=n-x;i++) //一共要放x个棋子,每行至多一个,所以需要x行
dfs(i,x); //从第i行开始,放x个棋子.按照按行递增的顺序访问,一定不会出现同行
cout<<sum<<endl;
}
}