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