zoukankan      html  css  js  c++  java
  • 状压dp总结

    状态压缩动态规划,就是我们俗称的状压DP,是利用计算机二进制的性质来描述状态的一种DP方式

    常见的用有选或不选(01,二进制),还有丧心病狂的三进制,四进制

    首先要熟练运用位运算

    1.判断一个数字x二进制下第i位是不是等于1。

    方法:if(((1<<(i1))&x)>0)if(((1<<(i−1))&x)>0)

    2.将一个数字x二进制下第i位更改成1。

    方法:x=x|(1<<(i1))x=x|(1<<(i−1))

    3.把一个数字二进制下最靠右的第一个1去掉。

    方法:x=x&(x1)

    然后是枚举子集,补集等

    首先是一道打基础的题

    关灯问题II 

    枚举,只是用到了位运算,好像不算状压

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int inf=0x3f;
    inline int read(){
        int x=0,k=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') k=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
        return k*x;
    }
    int a[105][15],f[1030];
    int main(){
    //    freopen(".in","r",stdin);
    //    freopen(".out","w",stdout);
        int n,m;
        memset(f,127,sizeof(f));
        n=read();m=read();
        for(int i=1;i<=m;i++)
            for(int j=1;j<=n;j++)
                a[i][j]=read();
    
        f[(1<<n)-1]=0;
        for(int i=(1<<n)-1;i>=0;i--){
            for(int j=1;j<=m;j++){
                int now=i;
                for(int k=1;k<=n;k++){
                    if(!a[j][k]) continue;
                    else if(a[j][k]==1&&((1<<(k-1))&i)) now^=(1<<(k-1));
                    else if(a[j][k]==-1&&!((1<<(k-1))&i)) now^=(1<<(k-1));
                }
                f[now]=min(f[now],f[i]+1);
            }
        }
        if(f[0]==2139062143) cout<<"-1";
        else cout<<f[0];
        return 0;
    }
    View Code

    [USACO06NOV]玉米田Corn Fields

    很明显的状压,先预处理第一行的状态,枚举后面的状态,对于每个状态,又枚举前一行的状态是否合法

    太暴力了qnq

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int mod=1e8;
    inline int read(){
        int x=0,k=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') k=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
        return k*x;
    }
    int dp[15][4100],map[15],a[15][15];
    bool pd[4100];
    int main(){
    //    freopen(".in","r",stdin);
    //    freopen(".out","w",stdout);
        int n,m;
        ll ans=0;
        n=read();m=read();
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){
                a[i][j]=read();
                map[i]=(map[i]<<1)+a[i][j];
            }
        for(int i=0;i<=(1<<m)-1;i++){
            if((((i>>1)&i)==0)&(((i<<1)&i)==0)){
                pd[i]=1;
            }
        }
        for(int i=0;i<=(1<<m)-1;i++){
            if(pd[i]&((i&map[1])==i)){
                dp[1][i]=1;
            }
        }
        for(int i=2;i<=n;i++)
            for(int j=0;j<=(1<<m)-1;j++){
                if(pd[j]&(j&map[i])==j){
                    for(int k=0;k<=(1<<m)-1;k++){
                        if((k&j)==0) dp[i][j]=(dp[i][j]+dp[i-1][k])%mod;
                    }
                }
            }
        for(int i=0;i<=(1<<m)-1;i++){
            ans=(ans+dp[n][i])%mod;
        }
        cout<<ans;
        return 0;
    }
    View Code
  • 相关阅读:
    【CF741D】Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu on tree)
    【CF600E】Lomsat gelral(dsu on tree)
    【Vijos】lxhgww的奇思妙想(长链剖分)
    【HDOJ6586】String(枚举)
    【HDOJ6578】Blank(DP)
    【HDOJ6583】Typewriter(SAM,DP)
    JAVA 集合 List 分组的两种方法
    HashMap的实现原理
    HashMap, HashTable, CurrentHashMap的区别
    java ThreadLocal(应用场景及使用方式及原理)
  • 原文地址:https://www.cnblogs.com/silent-pyb/p/9820402.html
Copyright © 2011-2022 走看看