zoukankan      html  css  js  c++  java
  • 状态压缩DP(棋盘类入门题(求方案数)+bitset解法)

    状态压缩DP(棋盘类入门题(求方案数)+bitset解法)

    反思

    • 将多个状态合并成(看成)一个状态来进行处理,并通过合并后的状态来优化问题的解决手段。
    • bitset是搭配状态压缩问题的一个很好用的工具。
    • 可以先对方案进行预处理,方便提取
    • 单行全为0的方案与其他所有方案都不冲突,可以增设一行,来吸收上一行的所有方案
    • 可行的方案数与行数没有直接挂钩。
    • 可以直接暴力,bitset写起来会比较麻烦一点

    AcWing 1064. 小国王

    #include<bits/stdc++.h>
    #define fir(i,a,b) for(int i=a;i<b;i++)
    using namespace std;
    typedef long long ll;
    const int N = 11;
    vector<bitset<N> > plans;
    vector<bitset<N> > suit[1<<N];
    
    bool check(bitset<N> x)
    {
    	if( ((x>>1)&x).any() || ((x<<1)&x).any() )
    	    return false;
    	return true; 
    }
    
    int cnt_king(bitset<N> x)//返回x中1的个数 
    {
        return x.count();    	
    } 
    
    int main()
    {
    	int n,k;
    	cin>>n>>k;
    	/****收集不连续站有两个国王的方案****/
    	fir(i,0,1<<n)
    	    if(check(i))
    		   plans.push_back(bitset<N>(i));
    	
    	fir(i,0,plans.size())
    	   fir(j,0,plans.size())
    	       if( check( plans[i] | plans[j] )  &&  ( plans[i] & plans[j] ).none() )//把二进制合并成一行,检查一下,同时还外加一个上下检查   
    		       suit[plans[i].to_ulong() ].push_back(plans[j]);
    		      
    	ll f[n+2][k+1][1<<n];//f[i][j][k]表示的是前i行以k的二进制状态表示来结尾并拥有已经拥有k位国王的方案数 
    	memset(f,0,sizeof(f));
    	f[0][0][0] = 1;//各种状态的起点; 
        for(int i=1;i<=n+1;i++)//行 
           for(int king=0;king<=k;king++)//国王量 
               for(int st=0;st<plans.size();st++)//可行方案的遍历 
                   for(int up=0;up<suit[ plans[st].to_ulong() ].size();up++ )//直接找到可靠的小伙伴 
    			       if(king-cnt_king(suit[ plans[st].to_ulong() ][up]) >=0 ) 
    			          f[i][king][plans[st].to_ulong() ] += f[i-1][ king-cnt_king(suit[ plans[st].to_ulong() ][up]) ][ suit[ plans[st].to_ulong() ][up].to_ulong() ]; 
           
        cout<<f[n+1][k][0]<<endl;//状态0和所有状态都不起冲突,且0的国王数本身就是0,相当于把上一行所有的国王都拿走   
    	return 0;
    }
    

    AcWing 327. 玉米田

    #include<bits/stdc++.h>
    #define fir(i,a,b) for(int i=a;i<b;i++)
    using namespace std;
    const int N = 13, Mod = 1e8;//N取13 
    int n,m;
    int dp[N][1<<N];//12*12*4096<4e8;
    bitset<N> row[N];
    vector<bitset<N> > plans;
    vector<bitset<N> > suit[(1<<N)/2];//这里写错了,N应该改为1<<N,1到1<<N 
    bool check(bitset<N> x)
    {
        return ( x<<1 & x).none() && ( x>>1 & x).none(); 
    }
    int count_corn(bitset<N> x)
    {
    	return x.count();
    }
    void init()
    {
    	memset(dp,0,sizeof(dp));
    }
    int main()
    {
    	cin>>n>>m;
    	init();
    	fir(i,1,n+1)
    	   fir(j,0,m)
    	   {
    	   	    int x;
    	   	    cin>>x;
    			row[i]<<=1;
    	   	    if(x)row[i].set(0);//bitset不能直接加整数 
    	   }
    
        fir(i,0,1<<m)//m写成n错了 
    	    if(check(i))
    	       plans.push_back(bitset<N>(i));
    
    	fir(i,0,plans.size())
            fir(j,0,plans.size())
                if( (plans[i]&plans[j]).none() )
                   suit[i].push_back(plans[j]);
        
    	dp[0][0]=1;
    	fir(i,1,n+2)
    	    fir(cur,0,plans.size())
    	        if( (plans[cur] & row[i] ) == plans[cur] )//方案和土地实际情况不冲突, 方案包括在土地的实际情况中 
    	           fir(up,0,suit[cur].size())
    				       dp[i][plans[cur].to_ulong()]=( dp[i][plans[cur].to_ulong()]+dp[i-1][ suit[cur][up].to_ulong()] ) % Mod;
    
    	cout<<dp[n+1][0];//汇合于一处 
    	return 0;
    }
    

    其他

    English

    • artillery:炮兵
    • The artillery bombarded the enemy all day.
  • 相关阅读:
    基于CodeSmith的三层架构代码模板
    全自动时代:JavaScript自动压缩插件
    NServiceBus最流行的开源企业服务总线 for .Net
    神奇的东西
    WebMatrix
    .Net TDD我用Machine.Specification
    JQuery Smart UI 简介(四) — 强大的适用性&存在问题【项目使用性介绍】
    JQuery Smart UI 简介(三)
    JQuery Smart UI 简介(二)
    基于WCF大型分布式系统的架构设计
  • 原文地址:https://www.cnblogs.com/BeautifulWater/p/15056110.html
Copyright © 2011-2022 走看看