POJ 1321 棋盘问题

17 篇文章 0 订阅

棋盘问题

这道题目与八皇后问题相似,唯一的区别就是n > m,这就使得棋盘中可能存在空行,即使某一行中有可以放的位置也不能选。这题的剪枝还是有很多可以考虑的。

我考虑了如下几个剪枝点:

1). 当剩余的可放位置小于剩余的要摆放棋子的个数的时候,就不需在继续搜索下去了,一定不会得到解。

2). 由于每一行每一列只能放置一个棋子,所以当剩余的行数小于剩余的棋子的个数的时候就不需要在搜索,一定得不到解。

代码如下:

#include<stdio.h>
#include<string.h>

bool row[10] ;
bool col[10] ;
int rnum[10] ;
int map[10][10] ;
int  ncount  ;

int n ;
int m ;
int nsum ;

int dfs(int pos , int num , int rest){
	
	if(num == m){
		ncount ++ ;
		return 1 ;
	}
	
	int i ;
	int j ;
	
	if(rest < m - num){
		return 0 ;
	}
	if(n - pos < m - num){
		return 0 ;
	}
	
	for(i = pos + 1 ; i <= n ; i ++){
		for(j = 1 ; j <= n ; j ++){
			if(!map[i][j] && !row[i] && !col[j]){
				map[i][j] = 1 ;
				row[i] = 1 ;
				col[j] = 1 ;
				dfs(i , num + 1 , rest - rnum[i]) ;
				map[i][j] = 0 ;
				row[i] = 0 ;
				col[j] = 0 ;
			}
		}
		rest = rest - rnum[i] ;
		
		if(rest < m - num){
			break ;
		}
		
		if(n - i < m - num){
			break ;
		}
	}
	
	return 0 ;
}

void work() {
	
	int i ;
	int j ;
	char str[10] ;
	
	memset(map , -1 , sizeof(map)) ;
	memset(row , 0 , sizeof(row))  ;
	memset(col , 0 , sizeof(col))  ;
	memset(rnum , 0 ,sizeof(rnum)) ;
	
	nsum = 0 ;
	ncount = 0 ;
	
	for(i = 1 ; i <= n ; i ++){
		scanf("%s" , str+1) ;
		
		for(j = 1 ; j <= n ; j ++){
				if(str[j]== '#'){
					map[i][j] = 0 ;
					rnum[i] ++ ;
					nsum ++ ;
				}
		}
	}
	
	if(nsum < m){
		printf("%d\n" , ncount) ;
		return ;
	}
	
	for(i = 1 ; i <= n ; i ++){
		for(j = 1 ; j <= n ; j ++){
			if(!map[i][j] && nsum >= m){
				row[i] = 1 ;
				col[j] = 1 ;
				map[i][j] = 1 ;
				dfs(i , 1 , nsum - rnum[i]) ;
				row[i] = 0 ;
				col[j] = 0 ;
				map[i][j] = 0 ;
			}
		}
		nsum = nsum - rnum[i] ;
		
		if(nsum < m){
			break ;
		}
		if(m > n - i){
			break ;
		}
	}
	
	printf("%d\n" , ncount) ;
}
int main(){

	while(scanf("%d %d" , &n , &m)!=EOF && n != -1 && m != -1){
		work() ;
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值