POJ 1321 简单搜索 回溯法 类n皇后问题

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

方法:回溯法

1.深搜函数的参数为行数。

2.used[i]=1表示第i列已摆棋子,这样可以减少搜索一列是否会冲突。

3.一行放一个,然后搜索下一行,这样可以减少搜索一行是否会冲突。

4.记得放一个棋子,记录个数。

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define inf 0x3f3f3f3f
using namespace std;
int n , k ;
int num ;
int cnt ;
char map1[10][10] ;
int used[10] ;//标记一列是否用过 
bool canplace(int x ,int y)
{
	int i , j ;
	int flag = 1 ;
	for(i = 0 ; i < x ; i ++)
	  if(map1[i][y] == '*')
		  	flag = 0 ;
	for(i = 0 ; i < y ; i ++)
	    if(map1[x][i] == '*')
		  	flag = 0 ;	
    return flag ;		  	
}
void dfs(int row)
{
	int i , j ;
	if(num == k)
	{	  
	    cnt ++ ;
	  return ;	
	}
	if(row == n)
	  return ;
	for(i = 0 ; i < n ; i ++)//一行放一个 
	{
		if(used[i] == 0 && map1[row][i] == '#')
		{
			used[i] = 1 ;
			num ++ ;
			dfs(row + 1) ;
			used[i] = 0 ;
			num -- ;
		}
	}
	dfs(row + 1) ;//有时候上面的for循环会一个都放不了导致无法到达下一层 
}
int main()
{
	int i , j ;
	char s[10] ;
	while(scanf("%d%d" , &n , &k) && !(n == -1 && k == -1))
	{
	  	for(i = 0 ; i < n ; i ++)
	  	{
	  	  scanf("%s" , &s) ;
		  for(j = 0 ; j < n ; j ++)
		     map1[i][j] = s[j] ;		
		}
		num = 0 ;
		cnt = 0 ;
		memset(used , 0 , sizeof(used)) ;
		dfs(0) ;
		printf("%d\n" , cnt) ;
    }
}

猜你喜欢

转载自blog.csdn.net/Irving0323/article/details/85327277