【BZOJ1087】【装压DP】互不侵犯King 题解

来源:互联网 发布:java线程同步 编辑:程序博客网 时间:2024/05/16 13:05

互不侵犯King

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

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

Output
  方案数。

Sample Input
3 2
Sample Output
16
装压DP
第一维存

/** * bzoj 1087 - D * Accepted * author:lemonoil */#include<iostream>#include<cstdio>using namespace std;int n,m,tot,sum[512];long long f[10][100][512];int p[512],g[512][512];long long ans,s;inline void read(int &res){    static char ch;int flag=1;    while((ch=getchar())<'0'||ch>'9')if(ch=='-')flag=-1;res=ch-48;    while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-48;res*=flag;}void init(){    for(register int i=0;i<=tot;i++)    if((i&(i>>1))==0){s=0;       for(register int x=i;x;x>>=1)s+=(x&1);       sum[i]=s,p[i]=1;    }    for(register int i=0;i<=tot;i++)if(p[i])        for(register int j=0;j<=tot;j++)if(p[j])            if(((i&j)==0)&&((i&(j>>1))==0)&&((j&(i>>1))==0))g[i][j]=1;}int main(){    read(n),read(m);    tot=(1<<n)-1;init();    for(register int i=0;i<=tot;i++)if(p[i])f[1][sum[i]][i]=1;    for(register int j=1;j<n;j++)        for(register int k=0;k<=tot;k++)if(p[k])            for(register int i=0;i<=tot;i++)if(p[i])if(g[k][i])                for(register int p=sum[k];p+sum[i]<=m;p++)                    f[j+1][p+sum[i]][i]+=f[j][p][k];    for(register int i=0;i<=tot;i++)ans+=f[n][m][i];    printf("%lld\n",ans);    return 0;}
阅读全文
0 0