zoukankan      html  css  js  c++  java
  • 【洛谷 P1896】[SCOI2005]互不侵犯(状压dp)

    题目链接
    题意:在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子。
    这是道状压(DP)好题啊。。
    定义状态:一个二进制数某一位为(1)表示该位放了国王,反之亦然。
    (f[i][j][k])表示,前(i)行,已经放了(j)个国王,并且第(i)的状态为(k)时的方案数。
    直接枚举所有状态显然不可行,于是可以先预处理去所有相邻两格不矛盾的状态,也就是每一行可能出现的状态。
    显然,当上一行的状态与该行的状态不矛盾时,状态能转移。
    所以,枚举这一行的状态和上一行的状态转移就行了,边界第一行所有状态的方案数都为(1)
    怎么判断矛不矛盾呢?
    把这一行的状态和上一行的状态进行按位与运算就能判断是否存在上下矛盾。
    但题目要求(2)个国王不能有公共顶点,把这行的状态左移一位再按位与,然后右移一位再按位与就行了。
    当三次与运算的结果都是(0)时,状态能转移。

    #include <cstdio>
    #define Open(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout);
    #define Close fclose(stdin);fclose(stdout);
    const int MAXN = 12;
    int n, k;
    int vis[MAXN][MAXN];
    int s[1024], p[1024];
    void dfs(int now, int S, int fi){   //dfs求出一行所有可能的状态,now是当前到第几位了,S是当前状态,fi是已经放了几个国王了
        if(now > n){
          s[++s[0]] = S; p[s[0]] = fi;
          return;
        }
        dfs(now + 1, S, fi);               //不放
        if(now == 1 || !(S & (1 << (now - 2)))) dfs(now + 1, S | (1 << (now - 1)), fi + 1);   //放
    }
    long long f[MAXN][MAXN * MAXN][1026];
    long long ans;
    int main(){
      scanf("%d%d", &n, &k);
      dfs(1, 0, 0);
      for(int i = 1; i <= s[0]; ++i)     //边界
         f[1][p[i]][i] = 1;
      for(int i = 2; i <= n; ++i)
         for(int j = 1; j <= s[0]; ++j)      //上一行状态
            for(int o = 1; o <= s[0]; ++o){     //该行状态
               if((s[j] & s[o]) || ((s[j] << 1) & s[o]) || ((s[o] << 1) & s[j])) continue;  //能转移
                 for(int l = p[o]; l <= k; ++l)           //转移
                    f[i][l][o] += f[i - 1][l - p[o]][j];
            }
      for(int i = 1; i <= s[0]; ++i) ans += f[n][k][i];
      printf("%lld
    ", ans);
      return 0;
    }
    
    
  • 相关阅读:
    个人总结一些常见的css问题
    工作中的js总结
    js面向对象
    js的一些特性
    js 实现改变字体大小
    将博客搬至CSDN
    最大连续子序列----DP动态规划
    捡石子---贪心算法(huffman)
    素数环问题---深度搜索遍历
    nyoj---12 喷水装置(二)--区间覆盖问题
  • 原文地址:https://www.cnblogs.com/Qihoo360/p/9606755.html
Copyright © 2011-2022 走看看