BZOJ1087

1087: [SCOI2005]互不侵犯King

Time Limit: 10 Sec   Memory Limit: 162 MB
Submit: 3235   Solved: 1878
[ Submit][ Status][ Discuss]

Description

  在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上
左下右上右下八个方向上附近的各一个格子,共8个格子。

Input

  只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)

Output

  方案数。

Sample Input

3 2

Sample Output

16



状压国王的摆放方案,预处理方案是否合法,

强行看错题...

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
long long dp[10][100][1000];
int n,k,hf[1<<10],kings[1<<10],htop;
int sum(int x){
	int ans=0;
	while(x>0)x-=x&-x,ans++;
	return ans;
}
bool check(int x,int y){
	return (hf[x]&hf[y])||((hf[x]<<1)&hf[y])||((hf[x]>>1)&hf[y]);
}
int main(){
	scanf("%d%d",&n,&k);
	if(n==1){
		printf("1");
		return 0;
	}
	for(int i=0;i<(1<<n);++i){
		for(int j=0;j<n;++j)if((i>>j)&1){
			if(j>0&&((i>>j-1)&1))goto end;
			else if(j<n-1&&((i>>j+1)&1))goto end;
		}
		hf[++htop]=i;
		end:;
	}
	for(int i=1;i<=htop;++i)kings[i]=sum(hf[i]);
	dp[0][0][1]=1;
	for(int i=0;i<n;++i)for(int j=0;j<=k;++j)
		for(int s=1;s<=htop;++s)if(dp[i][j][s]){
//			dp[i+1][j][1]+=dp[i][j][s];
			for(int w=1;w<=htop;++w)if(!check(s,w))
				if(kings[w]+j<=k)dp[i+1][j+kings[w]][w]+=dp[i][j][s];
		}
	long long ans=0;
	for(int s=1;s<=htop;++s)ans+=dp[n][k][s];
	printf("%lld",ans);		
		
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值