1. 程式人生 > >POJ 1321 簡單搜尋 回溯法 類n皇后問題

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) ;
    }
}