bzoj 1087 [SCOI2005]互不侵犯King 状态压缩dp

1087: [SCOI2005]互不侵犯King

Time Limit: 10 Sec  Memory Limit: 162 MB
[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<bits/stdc++.h>
using namespace std;
#define ll long long
#define esp 1e-13
const int N=5e2+30,M=1e6+50000,inf=1e9+10,mod=1000000007;
ll dp[10][N][90];
int check(int t)
{
    int num=t&(t<<1);
    if(num==0)
    return 1;
    return 0;
}
int check2(int i,int t)
{
    if((i&t)==0&&(i&(t>>1))==0&&(i&(t<<1))==0)
    return 1;
    return 0;
}
int get1(int t)
{
    int sum=0;
    while(t)
    {
        if(t&1)
        sum++;
        t>>=1;
    }
    return sum;
}
int main()
{
    int x,y,i,z,t;
    scanf("%d%d",&x,&y);
    dp[0][0][0]=1;
    int u=1;
    for(i=0;i<x;i++)
    u*=2;
    for(i=1;i<=x;i++)
    {
        for(t=0;t<u;t++)
        {
            if(!check(t))
            continue;
            for(int j=0;j<u;j++)
            {
                if(!check(j))
                continue;
                if(!check2(j,t))
                    continue;
                int hh=get1(t);
                for(int k=0;k+hh<=y;k++)
                dp[i][t][k+hh]+=dp[i-1][j][k];
            }
        }
    }
    ll ans=0;
    for(i=0;i<u;i++)
    ans+=dp[x][i][y];
    printf("%lld\n",ans);
    return 0;
}

 

posted @ 2016-08-13 15:56  jhz033  阅读(148)  评论(0编辑  收藏  举报