sgu223:Little Kings(状压DP)

来源:互联网 发布:埃菲尔铁塔数据 编辑:程序博客网 时间:2024/04/29 06:10

题目大意:
      一个nn的棋盘,放入k个棋子,两两不相邻(8个方向都算相邻)的方案数。n10,kn2

分析:
      就是一个简单的DPf[i][j][k]表示第i行放了j个棋子状态为k的方案数。

AC code:

#include <cstdio>#include <cstring>#include <iostream>typedef long long LL;#define get(s, i) ((s>>(i-1))&1)#define ONLINE_JUDGEconst int MAXN = 10, MAXK = 109;int n, k;int sta[1<<MAXN], tot, Map[1<<MAXN];LL f[2][MAXK][1<<MAXN];LL ans;void dfs(int g, int s, int now, int fl, int sum){    if(now == n+1)    {        for(int i = 0; i+sum <= k; ++i)            f[fl][i+sum][Map[s]] += f[fl^1][i][Map[g]];        return ;    }    dfs(g, s, now+1, fl, sum);    if(now > 1 && (get(s, now-1) || get(g, now-1))) return ;    if(get(g, now)) return ;    if(now < n && get(g, now+1)) return ;    if(sum+1 > k) return ;    dfs(g, s|(1<<(now-1)), now+1, fl, sum+1);}bool check(int s){    for(int i = 2; (1<<(i-1)) <= s; ++i)        if(get(s, i-1) && get(s, i)) return false;    return true;}int main(){    #ifndef ONLINE_JUDGE    freopen("sgu223.in", "r", stdin);    freopen("sgu223.out", "w", stdout);    #endif    std::ios::sync_with_stdio(0);    std::cin >> n >> k;    for(int i = 0; i < (1<<n); ++i)        if(check(i)) sta[++tot] = i, Map[i] = tot;    f[0][0][1] = 1;    for(int i = 1; i <= n; ++i)    {        memset(f[i&1], 0, sizeof(f[i&1]));        for(int j = 1; j <= tot; ++j)            dfs(sta[j], 0, 1, i&1, 0);    }    for(int i = 1; i <= tot; ++i)        ans += f[n&1][k][i];    std::cout << ans << std::endl;    #ifndef ONLINE_JUDGE    fclose(stdin);    fclose(stdout);    #endif    return 0;}
0 0