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

 

posted @ 2016-12-08 21:46  keshuqi  阅读(295)  评论(0编辑  收藏  举报