【HDU1693】Eat the Trees(插头dp)

【HDU1693】Eat the Trees(插头dp)

题面

HDU
Vjudge
大概就是网格图上有些点不能走,现在要找到若干条不相交的哈密顿回路使得所有格子都恰好被走过一遍。

题解

这题的弱化版本吧。。。
因为可以任意分配哈密顿回路的数量,因此根本不需要再考虑插头的配对问题了,那么直接分情况转移就好啦。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
#define MAX 13
inline int read()
{
    int x=0;bool t=false;char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=true,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return t?-x:x;
}
int bin[MAX];
ll f[MAX][MAX][1<<12];
int n,m;
int g[MAX][MAX];
int main()
{
    int T=read();
    bin[0]=1;for(int i=1;i<13;++i)bin[i]=bin[i-1]<<1;
    for(int TT=1;TT<=T;++TT)
    {
        n=read();m=read();memset(g,0,sizeof(g));memset(f,0,sizeof(f));
        for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j)
                g[i][j]=read();
        f[0][m][0]=1;int S=1<<(m+1);
        for(int i=1;i<=n;++i)
        {
            for(int k=0;k<S>>1;++k)f[i][0][k<<1]=f[i-1][m][k];
            for(int j=1;j<=m;++j)
                for(int k=0;k<S;++k)
                {
                    int left=(k>>(j-1))&1,up=(k>>j)&1;
                    if(!g[i][j])
                    {
                        if(!left&&!up)f[i][j][k]+=f[i][j-1][k];
                        continue;
                    }
                    if(!left&&!up)
                        if(g[i+1][j]&&g[i][j+1])f[i][j][k+bin[j-1]+bin[j]]+=f[i][j-1][k];
                    if(!left&&up)
                    {
                        if(g[i+1][j])f[i][j][k+bin[j-1]-bin[j]]+=f[i][j-1][k];
                        if(g[i][j+1])f[i][j][k]+=f[i][j-1][k];
                    }
                    if(left&&!up)
                    {
                        if(g[i+1][j])f[i][j][k]+=f[i][j-1][k];
                        if(g[i][j+1])f[i][j][k-bin[j-1]+bin[j]]+=f[i][j-1][k];
                    }
                    if(left&&up)f[i][j][k-bin[j-1]-bin[j]]+=f[i][j-1][k];
                }
        }
        printf("Case %d: There are %lld ways to eat the trees.\n",TT,f[n][m][0]);
    }
}

原文地址:https://www.cnblogs.com/cjyyb/p/10092309.html

时间: 2024-11-12 07:56:33

【HDU1693】Eat the Trees(插头dp)的相关文章

[hdu1693 Eat the Trees]插头dp

题意:用若干条回路覆盖01矩阵里面所有的1的方案数 方法:多回路问题,需要将插头的有无加入状态里,然后沿轮廓线转移即可.简单好写. #include <bits/stdc++.h> using namespace std; #ifndef ONLINE_JUDGE #include "local.h" #endif // ONLINE_JUDGE #define pb(x) push_back(x) #define mp(x, y) make_pair(x, y) #def

HDU 1693 Eat the Trees 插头DP

链接:http://acm.hdu.edu.cn/showproblem.php?pid=1693 题意:给出一块r*c的地,(r,c<=11),其中有的土地上种上了树,有些没有种上树,只能在种上树的地上走,通过走若干个回路,来走遍所有种树的土地.问有多少种走法. 思路:无论如何还是要先提供一个链接:http://wenku.baidu.com/view/4fe4ac659b6648d7c1c74633.html,是国家队论文,里面对于要提及的概念讲解的十分清楚. dp的过程是从左上角的点到右下

hdu1693:eat trees(插头dp)

题目大意: 题目背景竟然是dota!屠夫打到大后期就没用了,,只能去吃树! 给一个n*m的地图,有些格子是不可到达的,要把所有可到达的格子的树都吃完,并且要走回路,求方案数 题解: 这题大概是最简单的插头dp了.. 比陈丹琦论文里的例题还要简单,因为允许有多个回路,所以不需要存储插头之间的连通性,直接二进制状压 搞清楚插头和轮廓线的概念基本就可以做出来了 这里有一些资料http://www.docin.com/p-741918386.html 代码: #include <iostream> #

[Hdu 1693] Eat the Trees 轮廓线DP

题意 n * m 的矩形, 有坏点, 求划分成若干个回路的方案数. n, m <= 11 . 实现 1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cctype> 5 #define F(i, a, b) for (register int i = (a); i <= (b); i++) 6 #define LL long long 7 inlin

HDU1693 Eat the Trees

题目 插头dp,由于我们不需要判断曼哈段回路是否提前闭合,所以并不要括号序列,直接二进制状压一条轮廓线即可, \(1\)表示这个位置有插头,\(0\)表示没有 在考虑到\((i,j)\)我们考虑一下\((i,j-1)\)是否有向右的插头,\((i-1,j)\)是否有向下的插头 之后转移可以大力讨论一波 右没有下没有,那么必须在\((i,j)\)建一个转角,在\((i,j)\)新建一个向右和向下的插头 右有下有,那么必须在\((i,j)\)处闭合,于是在\((i,j)\)新建一个向左和向上的插头,

[入门向选讲] 插头DP:从零概念到入门 (例题:HDU1693 COGS1283 BZOJ2310 BZOJ2331)

转载请注明原文地址:http://www.cnblogs.com/LadyLex/p/7326874.html 最近搞了一下插头DP的基础知识……这真的是一种很锻炼人的题型…… 每一道题的状态都不一样,并且有不少的分类讨论,让插头DP十分锻炼思维的全面性和严谨性. 下面我们一起来学习插头DP的内容吧! 插头DP主要用来处理一系列基于连通性状态压缩的动态规划问题,处理的具体问题有很多种,并且一般数据规模较小. 由于棋盘有很特殊的结构,使得它可以与“连通性”有很强的联系,因此插头DP最常见的应用要数

插头DP学习

队内没人会插头DP,感觉这个不会不行...所以我还是默默去学了一下, 学了一天,感觉会了一点.对于每一行,一共有j+1个插头,如果是多回路类的题目, 比较简单,可以用1表示有插头,0表示没有插头,这样就可以愉快转移了, 对于当前出来的位置(i,j),与它有关的插头有j-1和j 那么我们可以枚举状态经行转移. 对于单回路的问题....只是了解思想,目前还不会写,太笨了=_= poj 2411 Mondriaan's Dream 题意:用1*2小方块组成n*m矩阵有多少种组成方式 思路:我们从上到下

状态压缩插头DP

HDU 1693   Eat the Trees http://www.cnblogs.com/zhuangli/archive/2008/09/04/1283753.html http://blog.csdn.net/xymscau/article/details/6756351 题意:在N*M(1<=N, M<=11)的矩阵中,有些格子有树,没有树的格子不能到达,找一条或多条回路,吃完所有的树,求有多少种方法. 分析:轮廓线表示当前插头的状态,这题中状态中1表示有插头,0表示无插头.如果是

【HDU】【1693】Eat The Trees

插头DP 插头dp模板题…… 这题比CDQ论文上的例题还要简单……因为不用区分左右插头(这题可以多回路,并不是一条哈密尔顿路) 硬枚举当前位置的状态就好了>_< 题解:http://blog.csdn.net/xymscau/article/details/6756351 1 //HDU 1693 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<iostream