zoukankan      html  css  js  c++  java
  • [HDU1693]Eat the Trees

    题面在这里

    题意

    四通格内有部分格子为障碍物,求用数个回路将非障碍物格子全部覆盖的方案数

    数据范围

    [1le n,mle 11 ]

    sol

    本人插头DP第一题
    入门首推CDQ大佬论文《基于连通性状态压缩的动态规划问题》

    插头指两个相邻元素之间是否相连的性质
    而插头DP以轮廓线上各个插头的状态
    转移时主要按格转移需要相当的时间讨论转移方程,
    因此是一种非常难写的状态压缩DP...

    这道题轮廓线上只要维护是否联通,也就是0/1两个状态,
    最后只要匹配完所有的插头就合法,稍微注意一下障碍物就行。

    其实没有学过插头DP的大佬们也是可以做出这种多回路问题的

    代码

    #include<bits/stdc++.h>
    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<iomanip>
    #include<cstring>
    #include<complex>
    #include<vector>
    #include<cstdio>
    #include<string>
    #include<bitset>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<set>
    #define pub push_back
    #define puf push_front
    #define pob pop_back
    #define pof pop_front
    #define RG register
    #define il inline
    using namespace std;
    typedef unsigned long long ull;
    typedef vector<int>VI;
    typedef long long ll;
    typedef double dd;
    const dd eps=1e-10;
    const int mod=1e8;
    const int N=13;
    il ll read(){
    	RG ll data=0,w=1;RG char ch=getchar();
    	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    	if(ch=='-')w=-1,ch=getchar();
    	while(ch<='9'&&ch>='0')data=data*10+ch-48,ch=getchar();
    	return data*w;
    }
    
    il void file(){
    	freopen("a.in","r",stdin);
    	freopen("a.out","w",stdout);
    }
    
    int T,c,mp[N][N];ll f[N][N][1<<N];
    il void solve(){
    	RG int n=read(),m=read(),p,q;
    	for(RG int i=1;i<=n;i++)
    		for(RG int j=1;j<=m;j++)mp[i][j]=read();
    	memset(f,0,sizeof(f));f[1][1][0]=1;
    	for(RG int i=1;i<=n;i++)
    		for(RG int j=1;j<=m;j++){
    			p=1<<(j-1);q=1<<j;
    			if(j==m){
    				if(!mp[i][j])
    					for(RG int k=0;k<(1<<(m+1));k++){
    						if(!(k&p)&&!(k&q))
    							f[i+1][1][k<<1]+=f[i][j][k];
    					}
    				else 
    					for(RG int k=0;k<(1<<(m+1));k++)
    						if((k&p)&&!(k&q))
    							f[i+1][1][k<<1]+=f[i][j][k];
    						else if(!(k&p)&&(k&q))
    							f[i+1][1][((k^q)|p)<<1]+=f[i][j][k];
    						else if((k&p)&&(k&q))
    							f[i+1][1][((k^q)^p)<<1]+=f[i][j][k];
    				continue;
    			}
    			if(!mp[i][j]){
    				for(RG int k=0;k<(1<<(m+1));k++)
    					if(!(k&p)&&!(k&q))f[i][j+1][k]+=f[i][j][k];
    			}
    			else {
    				for(RG int k=0;k<(1<<(m+1));k++)
    					if((k&p)&&(k&q))
    						f[i][j+1][(k^p)^q]+=f[i][j][k];
    					else if((k&p)&&!(k&q)){
    						f[i][j+1][(k^p)|q]+=f[i][j][k];
    						f[i][j+1][k]+=f[i][j][k];
    					}
    					else if(!(k&p)&&(k&q)){
    						f[i][j+1][(k|p)^q]+=f[i][j][k];
    						f[i][j+1][k]+=f[i][j][k];
    					}
    				else f[i][j+1][(k|p)|q]+=f[i][j][k];
    			}
    		}
    	printf("Case %d: There are %lld ways to eat the trees.
    ",++c,f[n+1][1][0]);
    }
    
    int main()
    {
    	T=read();while(T--)solve();return 0;
    }
    
  • 相关阅读:
    QAU 18校赛 J题 天平(01背包 判断能否装满)
    滚动数组
    Leapin' Lizards HDU
    Sabotage UVA
    Food HDU
    两个Button 加通一个手势,那么 第一个的就失效了,
    终于把聊天记录保存到数据库当中去了,
    添加好友,
    XEP 0055 (Jabber search) with iphone SDK
    手机ip,
  • 原文地址:https://www.cnblogs.com/cjfdf/p/8690085.html
Copyright © 2011-2022 走看看