Sgu棋盘覆盖系列

求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);




你可能感兴趣的:(java)