• 状压DP


    套路

    其实套路挺明显的,也很容易看出来要用状压,所以通常就把一行的状态压缩成一个数(一般适用于放不放棋子这类的只有选/不选两种状态的)
    (有可能会有特殊情况,比如炮兵阵地就是三进制状压,这个我们先不管)
    核心代码大概长这样,根据不同题的不同限制改一改就行了:

    void dp(){
    	f[0][0]=1;
    	for(int i=1;i<=m;i++){
    		for(int j=0;j<sum;j++){//< is rignt,<= is wrong,because 2^n-1 means every figure is 1 in binary system
    			if((j>num[i])||((j&num[i])!=j)||(j&(j<<1))||(j&(j>>1))) continue;
    			for(int k=0;k<sum;k++){
    				if(!(k&j)){
    					f[i][j]=(f[i][j]+f[i-1][k])%mod;
    				}
    			}
    		}
    	}
    }
    

    例题

    P1879 Corn Fields G

    题目
    code:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #define maxn 20
    #define ll long long
    using namespace std;
    template<typename T>
    inline void read(T &x){
    	x=0;bool flag=0;char c=getchar();
    	for(;!isdigit(c);c=getchar()) if(c=='-') flag=1;
    	for(;isdigit(c);c=getchar()) x=x*10+(c^48);
    	if(flag) x=-x;
    }
    
    const int mod=100000000;
    int m,n,a[maxn][maxn];
    int num[maxn],f[maxn][1<<maxn],sum,ans;
    
    void dp(){
    	f[0][0]=1;
    	for(int i=1;i<=m;i++){
    		for(int j=0;j<sum;j++){//< is rignt,<= is wrong,because 2^n-1 means every figure is 1 in binary system
    			if((j>num[i])||((j&num[i])!=j)||(j&(j<<1))||(j&(j>>1))) continue;
    			for(int k=0;k<sum;k++){
    				if(!(k&j)){
    					f[i][j]=(f[i][j]+f[i-1][k])%mod;
    				}
    			}
    		}
    	}
    }
    
    int main(){
    	read(m),read(n);
    	for(int i=1;i<=m;i++){
    		for(int j=1;j<=n;j++){
    			read(a[i][j]);
    			num[i]=(num[i]<<1)+a[i][j];
    		}
    	}
    	sum=1<<n;
    	dp();
    	for(int i=0;i<sum;i++) (ans+=f[m][i])%=mod;
    	cout<<ans<<endl;
    	return 0;
    } 
    

    P1896 互不侵犯

    题目
    因为限制了k个国王,所以f数组要多开一维记一下国王数量
    code:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #define maxn 15
    #define maxm 200
    #define ll long long//不开long long要出锅啊 
    using namespace std;
    template<typename T>
    inline void read(T &x){
    	x=0;bool flag=0;char c=getchar();
    	for(;!isdigit(c);c=getchar()) if(c=='-') flag=1;
    	for(;isdigit(c);c=getchar()) x=x*10+(c^48);
    	if(flag) x=-x;
    }
    
    int n,k;
    ll ans,king_yihang,cnt,a[maxm],num[maxm],f[maxn][maxm][maxm];//第i行第j种状态放了k个国王 
    
    void dp(){
    	f[0][1][0]=1;
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=cnt;j++){
    			for(int t=0;t<=k;t++){
    				if(num[j]>t) continue;
    				for(int u=1;u<=cnt;u++){
    					if((a[u]&a[j])||(a[u]&(a[j]<<1))||(a[u]&(a[j]>>1))) continue;
    					f[i][j][t]+=f[i-1][u][t-num[j]];
    				}
    			}
    		}
    	} 
    }
    
    int main(){
    	read(n),read(k);
    	for(int i=0;i<=(1<<n)-1;i++){
    		king_yihang=0;
    		if(i&(i<<1)) continue;
    		for(int j=0;j<=n-1;j++) if(i&(1<<j)) king_yihang++;
    		a[++cnt]=i;
    		num[cnt]=king_yihang;
    	}
    	dp();
    	for(int i=1;i<=cnt;i++) ans+=f[n][i][k];
    	cout<<ans<<endl;
    	return 0;
    }
    

    P4163 排列

    题目
    code:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #define maxn 1010
    #define ll long long
    using namespace std;
    template<typename T>
    inline void read(T &x){
    	x=0;bool flag=0;char c=getchar();
    	for(;!isdigit(c);c=getchar()) if(c=='-') flag=1;
    	for(;isdigit(c);c=getchar()) x=x*10+(c^48);
    	if(flag) x=-x;
    }
    
    int T,d,len,num[20],f[1024][maxn];
    char s[20];
    bool vis[20];
    
    int main(){
    	read(T);
    	for(int t=1;t<=T;t++){
    		memset(s,0,sizeof(s));
    		memset(num,0,sizeof(num));
    		memset(f,0,sizeof(f));
    		cin>>s+1;read(d);
    		len=strlen(s+1);
    		for(int i=1;i<=len;i++) num[i]=s[i]-'0';
    		f[0][0]=1;
    		for(int i=0;i<(1<<len)-1;i++){
    			memset(vis,0,sizeof(vis));
    			for(int j=1;j<=len;j++){
    				if((i&(1<<(j-1)))||vis[num[j]]) continue;
    				vis[num[j]]=1;
    				for(int k=0;k<d;k++){//********
    					f[i|(1<<(j-1))][(10*k+num[j])%d]+=f[i][k];
    				}
    			}
    		}
    		cout<<f[(1<<len)-1][0]<<endl;
    	}
    	return 0;
    } 
    

    P2150 寿司晚宴

    题目
    没写呢,写完再来填坑

  • 相关阅读:
    R镜像源的切换
    GWAS中的名称概念
    mac显示隐藏的文件,安装cocoapods
    swift开发笔记28 SlideBarMenu
    MAC读取安卓手机的APP的log日志
    关于DES加密中的 DESede/CBC/PKCS5Padding
    swift开发笔记27 UserNotifications
    swift开发笔记26 3D Touch
    银联Pos终端签到、签退、批结算、批上送、PinKey、MacKey、KEK、主密钥、工作密钥、TPDU、报文头
    开发感悟
  • 原文地址:https://www.cnblogs.com/DReamLion/p/14811275.html
Copyright © 2020-2023  润新知