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 }

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

  • 相关阅读:
    HDU 2852 KiKi's K-Number (主席树)
    HDU 2089 不要62
    Light oj 1140 How Many Zeroes?
    Bless You Autocorrect!
    HDU 6201 transaction transaction transaction
    HDU1561 The more ,The better (树形背包Dp)
    CodeForces 607B zuma
    POJ 1651 Mulitiplication Puzzle
    CSUOJ 1952 合并石子
    Uva 1599 Ideal path
  • 原文地址:https://www.cnblogs.com/lidaxin/p/4891455.html
Copyright © 2011-2022 走看看