Little Kings - SGU 223(状态压缩)

题目大意:在一个N*N的棋盘上放置M个国王,已知国王会攻击与它相邻的8个格子,要求放置的额国王不能相互攻击,求放置的方式有多少种。

分析:用dp[row][state][nOne],表示本行状态state时候的放置国王nOne时候情况有多少种,状态转移也比较简单了.....

代码如下:

===================================================================================================================================

#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;

const int MAXN = 1<<10;

bool G[MAXN][MAXN];
int bit[MAXN], cnt, N, M;
int one[MAXN];
long long dp[12][MAXN][107];

void DFS(int k, int state, int nOne)
{
    if(k >= N)
    {
        one[cnt] = nOne;
        bit[cnt++] = state;
        return ;
    }
    DFS(k+1, state, nOne);
    DFS(k+2, state|(1<<k), nOne+1);
}

int main()
{
    scanf("%d%d", &N, &M);

    DFS(0, 0, 0);

    for(int i=0; i<cnt; i++)
    for(int j=i; j<cnt; j++)
    {
        if((bit[i]&bit[j])+(bit[i]&(bit[j]<<1))+(bit[i]&(bit[j]>>1))==0)
            G[bit[i]][bit[j]] = G[bit[j]][bit[i]] = true;
    }

    dp[0][0][0] = 1;

    for(int i=1; i<=N; i++)
    for(int j=0; j<cnt; j++)
    for(int k=0; k<cnt; k++)
    {
        if(G[bit[j]][bit[k]])
        {
            for(int t=one[j]; t<=M; t++)
            {
                dp[i][j][t] += dp[i-1][k][t-one[j]];
            }
        }
    }

    long long ans=0;

    for(int i=0; i<cnt; i++)
        ans += dp[N][i][M];

    printf("%lld\n", ans);

    return 0;
}

 

posted @ 2015-10-04 10:52  无忧望月  阅读(382)  评论(0)    收藏  举报
levels of contents