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;
    }
    
  • 相关阅读:
    Restful接口传入多参数
    map转换成JSON的3种方式
    项目打包后执行start.sh提示“no such file or directory”解决办法,linux中给文件增加权限
    如何将一个a表a1字段与b表b1字段的笛卡尔积插入到e表中
    get、set方法的取代注释之lombok插件
    推荐 33 个 IDEA 最牛配置转(Java技术栈)
    mysql-----group by 对多个字段进行分组
    mysql获取某段时间内每一天的统计数据
    发票流水号生成方式
    postman之post请求传参
  • 原文地址:https://www.cnblogs.com/cjfdf/p/8690085.html
Copyright © 2011-2022 走看看