求n*n的棋盤上放K個象的放法, 象可以對角線相互攻擊
解法:把紅色方格從棋盤中抽出,再將棋盤和小方格都旋轉45°再壓縮,由於兩種顏色的棋盤互不攻擊,印刻可以看成兩個棋盤,格子棋盤上變為放只能上下攻擊的車的個數(詳見黑書p244)。
Sgu 221 Big Bishops
解法同上,只是把資料放大了,超long long ,用java裡的BigInteger
.
Sgu 222 Little Rooks
用組合數學或者sug220的方法 可以很快求解,狀態壓縮則需要
當k>=n時,時間複雜度為O(n*2^n)
當k<n時,時間複雜度為O(n*2^n*2^n),想不到更快的...
.
Sgu 223 Little King
n*n的棋盤上放k個King,King可攻擊它周圍的8個格子,用二進位表示一行放King的情況,1放,0不放。
比如n=3時,有000、001、010、011、100、101、110、111,8种放法,其中只有第1、2、3、5、6這幾種是合法的.首先對於一行求出可行的狀態,並同時統計出這個狀態放了幾個King,用num[j]表示
dp[i][j][k] 表示第i行的狀態為j,前i行一共放了k個King的總放法,
用(j&k) == 0 &&(j&(k>>1) == 0 && (j&(k<<1) == 0 表示j狀態中位置為1(即這個位置放一個King)的正上方、左上方和右上方都為0,這時則有 dp[i][j][k]+=dp[i-1][t][k-num[j]] 時間複雜度O(n*k*tot*tot) 對於n=10 tot=144,
Sgu 224 Little Queens
求n*n的棋盤上放K個Queens的總放法,Queens可以垂直、水平,對角線相互攻擊,詳見《位元運算應用進階》那篇文章,直接上代碼。
void dfs(int lev,int row,int left,int right,int num){if(num==k){ans++;return;}if(lev>n)return;int pos=max&(~(row|left|right));//max=(1<<n)-1;dfs(lev+1,row,left<<1,right>>1,num);while(pos!=0){int p=(pos&-pos);pos-=p;dfs(lev+1,row+p,(left+p)<<1,(right+p)>>1,num+1);}}ans=0;dfs(1,0,0,0,0);