首页 > 代码库 > bzoj[1087][SCOI2005]互不侵犯King

bzoj[1087][SCOI2005]互不侵犯King

Description

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

Input

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

Output

  方案数。

Sample Input

3 2

Sample Output

16

题解

#include<stdio.h>int n,m;bool st[600],ts[600][600];long long sum[600],f[2][121][600];int main(){    scanf("%d%d",&n,&m);    for(int i=0;i<(1<<n);i++)        if(!((i>>1)&i)){            for(int x=i;x;x>>=1)                sum[i]+=x&1;            st[i]=1;        }    for(int i=0;i<(1<<n);i++){        if(!st[i])            continue;        for(int j=0;j<=i;j++)            if(st[j]&&(!(i&j))&&(!(i&(j>>1)))&&(!((i>>1)&j)))                ts[i][j]=ts[j][i]=1;    }    int c=0;    for(int i=0;i<(1<<n);i++)        f[c][sum[i]][i]=1;    for(int t=1;t<n;t++){        c^=1;        for(int i=0;i<(1<<n);i++)            for(int j=0;j<=m;j++)                f[c][j][i]=0;        for(int i=0;i<(1<<n);i++){            if(!st[i])                continue;            for(int j=0;j<(1<<n);j++)                if(st[j]&&ts[i][j])                    for(int p=sum[j];p<=m-sum[i];p++)                        f[c][p+sum[i]][i]+=f[c^1][p][j];        }    }    long long ans=0;    for(int i=0;i<(1<<n);i++)        ans+=f[c][m][i];    printf("%lld\n",ans);    return 0;}

 

bzoj[1087][SCOI2005]互不侵犯King