搜索与回溯:棋盘问题

1217:棋盘问题


时间限制: 1000 ms         内存限制: 65536 KB
提交数: 5754     通过数: 2662 

【题目描述】

在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放 kk 个棋子的所有可行的摆放方案 CC。

【输入】

输入含有多组测试数据。

每组数据的第一行是两个正整数n,kn,k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 (n≤8,k≤n)(n≤8,k≤n)

当为−1 −1−1 −1时表示输入结束。

随后的nn行描述了棋盘的形状:每行有nn个字符,其中 ## 表示棋盘区域,.. 表示空白区域(数据保证不出现多余的空白行或者空白列)。

 

【输出】

对于每一组数据,给出一行输出,输出摆放的方案数目CC(数据保证C<231C<231)。

【输入样例】

2 1
#.
.#
4 4
...#
..#.
.#..
#...
-1 -1

【输出样例】

2
1

以前常见的搜索题是搜索方向,这里是棋子放置问题,不能放在同一行也不能放在同一列,所以这里p[]只用一维数组。p[j]表示第j个棋子是否落子了。

#include
#include
using namespace std;
bool p[9];
char a[9][9];
int x,y,n,k,ans=0;
void dfs(int x,int y)
{
	if(y == k)//判断是否落满棋子 
	{
		ans++;//方案数+1 
		return ;
	}
	for(int i = x; i <= n; ++i)//从第x行开始,x行是上一行+1 
	{
		for(int j = 1; j <= n; ++j)//当前行搜索每一列
		{
			if(a[i][j] == '#' && p[j] == false)//判断当前行能落子并且没有落过子 
			{
				p[j] = true;
				dfs(i+1,y+1);//搜索下一行 
				p[j] = false;
			}
		 } 
	 } 
	 return ;
 } 
int main()
{
	while(cin >> n >> k)//n*n的棋盘,摆放k个棋子
	{
		if(n==-1 && k==-1) return 0;
		memset(p,false,sizeof(p));//都没落过子 
		for(int i = 1; i <= n; ++i)
		{
			for(int j = 1; j <= n; ++j)
			{
				cin >> a[i][j];
			}
		}
		ans = 0;
		dfs(1,0);//从第一行开始搜索,落子数初始化为1 
		cout << ans << endl;
	 } 
	return 0;
}

 

你可能感兴趣的:(搜索)