POJ1321 棋盘问题【简单搜索】

棋盘问题

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 67775   Accepted: 32273

Description

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

Source

蔡错@pku

问题链接POJ1321 棋盘问题

解题思路

dfs

AC的C++代码

#include<iostream>

using namespace std;
const int N=15;

char b[N][N];
int ans,k,n;

//放置第几颗棋子,从第s行开始放,标记放在第j列是否合法  
void dfs(int i,int s,bool vis[])
{
	if(i==k+1){//已经有k个棋子放置好了,则结果加一 
		ans++;
		return;
	} //第i个棋子可以选择放置在s行~n-k+i行的某一行,由于已经放置了i-1个棋子,
	 //还差k-i+1个棋子,因此至少需要k-i+1行,所以第i个棋子最多放置在第n-k+i行 
	for(int r=s;r<=n-k+i;r++)//考虑把第i个棋子放置在第r行上 
	  for(int j=1;j<=n;j++)
	    if(b[r][j]=='#'&&!vis[j]){//第r行上只有为棋盘的列且没有放置棋子的列才可以放置 
	    	vis[j]=true;//考虑把第i个棋子放置在第r行的j列上,标记 
	    	dfs(i+1,r+1,vis); 
	    	vis[j]=false;//考虑不把第i个棋子放置在第r行的j列上,取消标记 
		}
}

int main()
{
	while(~scanf("%d%d",&n,&k)){
		if(n==-1&&k==-1)
		  break;
		ans=0;
		for(int i=1;i<=n;i++)
		  for(int j=1;j<=n;j++)
		    scanf(" %c",&b[i][j]);
		bool vis[N]={false};
		dfs(1,1,vis);
		printf("%d\n",ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/SongBai1997/article/details/82834369