USACO 八皇后问题扩展

http://ace.delos.com/usacoprob2?a=lPFJMyj6B9f&S=checker

本题的N的范围为:6<=N<=13,很显然普通的DFS搜索会超时,这里用到了位运算来加速,用三个变量left,right,mid来标记当前行的摆放状态。 left为向左的状态,right为向右的状态,mid为当前的状态。在转移到下一行的时候,三者的变化情况是:

left = left <<1 ;

right = right >> 1;

mid = mid ;

以下是参考代码:

/*
TASK : checker
ID : chris
LANG: C++
*/
#include<stdio.h>
#include<string.h>
int N;
int ans[15] ;
int left , right ,mid ,cnt;
void dfs(int row,int l,int r, int m){
	int left , mid ,right;
	if(row == N+1){
		cnt++;
		if(cnt > 3)	return ;
		printf("%d",ans[1]);
		for(int i=2;i<=N;++i){
			printf(" %d",ans[i]);	
		}	
		printf("\n");
		return ;
	}
	int s = ( (m|r)|l ) ;
	bool ok = 0 ;
	
	for(int i=1;i<=N;++i){
		if( ( s&(1<<(i-1)) )!=0 )	continue ;
		mid = (m | (1<<(i-1))) ;
		left = 	(l | (1<<(i-1))) ;
		right = (r | (1<<(i-1))) ;
		left = ( left << 1 ) ;
		right = (right >> 1) ;
		ans[row] = i ;
		dfs(row+1,left,right,mid);
	}
}
int main(){
	//freopen("checker.in","r",stdin);
	//freopen("checker.out","w",stdout);
	while(scanf("%d",&N)!=EOF){
		cnt = 0;
		for(int i=1;i<=N;++i){
			left = right = mid = 0 ;
			ans[1] = i ;
			mid = ( mid|(1<<(i-1)) ) ;
			left = right = mid ;		//左对角线标记 
			left = (left << 1) ;		//右对角线标记 
			right = (right >> 1) ;
			dfs(2,left ,right, mid) ;
		}
		printf("%d\n",cnt);
	}	
	return 0 ;	
}


你可能感兴趣的:(USACO 八皇后问题扩展)