zoukankan      html  css  js  c++  java
  • 洛谷1377 M国王 (SCOI2005互不侵犯King)

    洛谷1377 M国王 (SCOI2005互不侵犯King)

    本题地址: http://www.luogu.org/problem/show?pid=1377

    题目描述

       天天都是n皇后,多么无聊啊。我们来一道m国王游戏吧!
       题目是这样的,在n*n的格子里放m个国王,使他们不互相攻击,有多少种放法呢?(可以为0)
       国王的攻击力大不如皇后,他只能对与他相邻的8个格子产生攻击。

    输入输出格式

    输入格式:

    n,m

    输出格式:

    方案数

    输入输出样例

    输入样例#1:

    1 1

    输出样例#1:

    1

    说明

    数据范围:
    100%的数据满足n<=8,m<=n*n
    时限2秒(保证正常代码可以在时限内通过)

    【思路】

       状态压缩DP。

       注意这个题与n皇后的差别:可以有多个国王放在同一行。

       设d[i][s1][j]表示放到第i行 第i行放置状态为s1 且已经放了j个 的方案数。s用二进制表示。则有转移方程如下:

         d[i][s1][j] += d[i-1][s2][j-cnt[s1]]

       其中cnt表示状态中放置的国王数。

       优化:注意到不是每一个状态都是有用的,也不是任两个状态可以互相转移。因此可以提前筛去自身不符合要求的状态(can),同时建立状态之间的边(has_edge)。

     

    【代码】

     1 #include<iostream>
     2 #include<cstring>
     3 using namespace std;
     4 
     5 const int maxn = 1<<9;
     6 
     7 typedef long long LL;
     8 LL d[9][maxn][9*9];
     9 int cnt[maxn];
    10 bool has_edge[maxn][maxn];
    11 bool can[maxn];
    12 int n,m,all;
    13 
    14 void get_edge() {
    15     for(int i=0;i<all;i++) if((i&i>>1)==0)
    16     {
    17        can[i]=true;
    18        for(int j=0;j<n;j++) if(i&(1<<j)) cnt[i]++;
    19        for(int j=0;j<all;j++) 
    20           if(((i&j)==0) && ((i>>1)&j)==0 && ((j>>1)&i)==0) 
    21              has_edge[i][j]=true;
    22     }
    23 }
    24 
    25 int main() {
    26     cin>>n>>m;
    27     all=1<<n;
    28     
    29     get_edge();
    30     for(int s=0;s<all;s++) if(can[s]) d[1][s][cnt[s]]=1;
    31     
    32     for(int i=2;i<=n;i++)
    33        for(int s1=0;s1<all;s1++) if(can[s1])
    34           for(int j=cnt[s1];j<=m;j++)
    35           {
    36              for(int s2=0;s2<all;s2++) if(can[s2] && has_edge[s1][s2])
    37                 d[i][s1][j] += d[i-1][s2][j-cnt[s1]];
    38           }
    39     LL ans=0;
    40     for(int s=0;s<all;s++)  ans += d[n][s][m];
    41     cout<<ans;
    42     return 0;
    43 }

       另外一定要注意二进制的运算优先级,不确定的时候就加括号。

  • 相关阅读:
    002-Linux下防火墙相关命令操作
    001-网卡配置
    vs2012中自带IIS如何让其他电脑访问
    001-Mono for android在vs2012中发布设置
    小知识:utf-8和utf8mb4字符集
    Maven 模块化开发
    JUnit 单元测试
    解决8080端口占用问题
    (三)Tomcat服务器 -------JavaWeb的学习之路
    (一)走进JavaWeb的世界 -------JavaWeb的学习之路
  • 原文地址:https://www.cnblogs.com/lidaxin/p/4891455.html
Copyright © 2011-2022 走看看