zoukankan      html  css  js  c++  java
  • SCOI2005 互不侵犯

    传送门

    这道题看数据范围<=9,很容易想到是状压DP。

    根据各位dalao的讲述,状压DP中经常把每一个行的情况都压缩起来,之后进行DP。那么这样的话想起DP的状态就比较简单,dp[i][j][s]表示枚举到第i行,第i行的状态为j,算上当前行一共放了s个国王一共有多少种情况。其中j是一个二进制串,某一位是1代表该位有国王,否则没有。

    那么dp方程就是: dp[i][j][s] = sum{dp[i-1][k][s-num[j]]},其中k是上一行能取到的状态,num指的是本行这种状态(j)中一共有几个国王。其中i,j,k,s都是枚举的。

    不过算来直接枚举会超时……思考一下,因为国王是互不侵犯的,所以对于每一行来说,肯定有很多种状态是根本不可选择的。那我们先预处理出所有可能存在的情况再去枚举。方法很简单,对于状态i,如果i&(i<<1),那么就说明当前的状态是不可选择的。直接排除掉即可。

    之后,对于每两行的情况,我们仿照上面的做法&一下即可。比如当前两行的状态为x,y,如果x&y || x&(y<<1)|| (x<<1 )& y说明这两种状态之间是不可转移的(因为会互相侵犯)

    这样进行转移就可以了,注意要预处理第一行的所有情况。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    
    using namespace std;
    const int M = 10;
    typedef long long ll;
    
    ll read()
    {
        ll ans = 0,op = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
        {
            if(ch == '-') op = -1;
            ch = getchar();
        }
        while(ch >= '0' && ch <= '9')
        {
            ans *= 10;
            ans += ch - '0';
            ch = getchar();
        }
        return ans * op;
    }
    ll n,k,dp[M][1<<M][M<<2],gk[1<<M],ans,cnt,num[1<<(M+1)];
    
    ll getsum(ll x)
    {
        ll cur = 0;
        while(x) cur += (x&1),x >>= 1;
        return num[cnt] = cur;
    }
    int main()
    {
        n = read(),k = read();
        rep(i,0,(1<<n)-1) if(!(i&(i<<1))) gk[++cnt] = i,dp[1][cnt][getsum(i)] = 1;//第一行的预处理,同时处理出所有可行状态
        rep(i,2,n)
        rep(j,1,cnt)
        {
            ll x = gk[j];
            rep(p,1,cnt)
            {
                ll y = gk[p];
                if((x & y) || (x & (y << 1)) || ((x << 1) & y)) continue;//排除不可转移的情况
                rep(q,0,k) if(q >= num[j]) dp[i][j][q] += dp[i-1][p][q-num[j]];//把可行的情况加上即可
            }
        }
        rep(i,1,cnt) ans += dp[n][i][k];
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    线段树专辑—— pku 1436 Horizontally Visible Segments
    线段树专辑——pku 3667 Hotel
    线段树专辑——hdu 1540 Tunnel Warfare
    线段树专辑—— hdu 1828 Picture
    线段树专辑—— hdu 1542 Atlantis
    线段树专辑 —— pku 2482 Stars in Your Window
    线段树专辑 —— pku 3225 Help with Intervals
    线段树专辑—— hdu 1255 覆盖的面积
    线段树专辑—— hdu 3016 Man Down
    Ajax跨域访问
  • 原文地址:https://www.cnblogs.com/captain1/p/9557370.html
Copyright © 2011-2022 走看看