回溯法 POJ 1321:棋盘问题

总时间限制: 
1000ms
内存限制: 
65536kB
描述
在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。
输入
输入含有多组测试数据。
每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n
当为-1 -1时表示输入结束。
随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。
输出
对于每一组数据,给出一行输出,输出摆放的方案数目C (数据保证C<2^31)。
样例输入
2 1
#.
.#
4 4
...#
..#.
.#..
#...
-1 -1
样例输出
2

1

#include <iostream>
using namespace std;
int pan[10][10];
int coun=0;
bool flag[10];
void putfunction(int t,int num,int N){
	for(int i=0;i<N;i++){
		if(pan[t][i]==1&&!flag[i]){ //如果该行可以放棋子 
			if(num==1){ //如果该行是最后一行,方法计数值加一 
				coun++;
			}
			else{
				flag[i]=true; //若不是最后一行,置该列为已占用 
/**因为棋子数可能小于行数,所以下一个棋子开始的行数要从下一行遍历到N-num-1行**/
			    for(int j=t+1;j<=N-num+1;j++){  
				    putfunction(j,num-1,N);
			    }
			    flag[i]=false;	//退回上一层,将占用位清空 
			}
		}
	}
}
int main(){
	int N,K;
	char input[10];
	while(1){
		scanf("%d%d",&N,&K);
		if(N==-1&&K==-1){
			break;
		}
		for(int i=0;i<N;i++){
			scanf("%s",&input);
			for(int j=0;j<N;j++){
				if(input[j]=='.'){
					pan[i][j]=-1;
				}
				else{
					pan[i][j]=1;
				}
			}
		}
		for(int i=0;i<N;i++){
			flag[i]=false;
		}
		coun=0;
/**第一行的起始位置要从0开始遍历到N-K+1**/ 
        for(int i=0;i<=N-K+1;i++){
        	putfunction(i,K,N);
		}
		printf("%d\n",coun);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/xiao_chen_l/article/details/80099377