• 【一天一DP计划】状压DP


    ##P1896 互不侵犯【状压dp】

    • 用01串表示每一行的可行解
    • 列与列之间的限制条件在转移的时候continue
    • x&=(-x)可以找到x的二进制位上有多少个1
    • 关于位运算的优先级!不确定就无脑加括号哦哦
    reference:
    	https://www.luogu.org/blog/virus2017/1896dnqec
    Date:
    	2019.10.04
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    #define dwn(i,a,b) for(int i=a;i>=b;--i) 
    template <typename T> inline void rd(T &x){x=0;char c=getchar();int f=0;while(!isdigit(c)){f|=c=='-';c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}x=f?-x:x;} 
    #define mem(a,b) memset(a,b,sizeof(a))
    
    int f[9+5][512+5][81+5];
    //f[i][j][k]表示第i行的状态选的是第j个状态,有k个国王的方案数
    //上个状态:f[i-1][jj][k-cnt[j]]; 
    int n,K,tot;
    int st[512+5],cnt[512+5];
    //st表示当前可行的状态(01串 
    //cnt表示st[]的状态有多少个1(为了后面利用背包的思想转移) 
    
    inline void get_num(int x){
    	int now=0;
    	while(x){
    		x&=(x-1);
    		now++;
    	}
    	cnt[tot]=now;
    }
    
    inline void pre_work(){
    	for(int i=0;i<(1<<n);++i)
    		if(!(i&(i<<1)))//遇到位运算最好加括号,比如不能写成i&(-i)==0(==优先级比&高) 
    			st[++tot]=i,get_num(i);
    }
    
    #undef int
    int main(){
    #define int long long
    	#ifdef WIN64 
    	freopen("qinfan.txt","r",stdin);
    	#endif 
    	rd(n),rd(K);
    	pre_work();
    	rep(i,1,tot)f[1][i][cnt[i]]=1;
    	rep(i,2,n)
    		rep(j,1,tot)
    			rep(jj,1,tot){
    				if(st[j]&st[jj] || (st[j]<<1)&st[jj] || (st[j]>>1)&st[jj])continue;
    				dwn(k,K,cnt[j])
    					f[i][j][k]+=f[i-1][jj][k-cnt[j]];
    			} 
    	int ans=0;
    	rep(i,1,tot)
    		ans+=f[n][i][K];
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    C#和Modbus通信工程
    C#中JS和Flash中AS 3.0通信交互
    创建型-建造者模式(Builder)
    结构型-享元模式(Flyweight)
    行为型-模板方法模式(Template Method)
    创建型-原型模式(Prototype)
    行为型-状态模式(State)
    结构型-桥接模式(Bridge)
    行为型-中介者模式(Mediator)
    行为型-备忘录模式(Memento)
  • 原文地址:https://www.cnblogs.com/sjsjsj-minus-Si/p/11634651.html
Copyright © 2020-2023  润新知