HDU1693 Eat the Trees

题目

插头dp,由于我们不需要判断曼哈段回路是否提前闭合,所以并不要括号序列,直接二进制状压一条轮廓线即可, \(1\)表示这个位置有插头,\(0\)表示没有

在考虑到\((i,j)\)我们考虑一下\((i,j-1)\)是否有向右的插头,\((i-1,j)\)是否有向下的插头

之后转移可以大力讨论一波

右没有下没有,那么必须在\((i,j)\)建一个转角,在\((i,j)\)新建一个向右和向下的插头

右有下有,那么必须在\((i,j)\)处闭合,于是在\((i,j)\)新建一个向左和向上的插头,和原来的插头连接

右有下没有,先新建一个向左的插头,之后可以再来一个向右的插头,或者转向一下建一个向下的插头

右没有下有,先新建一个向下的插头,之后可以再来一个向下的插头,或者转向一下建一个向右的插头

转移的时候考虑新建插头对轮廓线的影响就好了

代码

#include<bits/stdc++.h>
#define re register
#define LL long long
int a[13][13],len,T;
LL dp[2][(1<<13)+1];
inline void upd(int &val,int pos,int v){--pos;val&=(len^(1<<pos));val|=(v<<pos);}
inline void solve() {
    int n,m;scanf("%d%d",&n,&m);len=(1<<(m+1))-1;
    for(re int i=1;i<=n;i++)
        for(re int j=1;j<=m;j++) scanf("%d",&a[i][j]);
    int o=0;memset(dp,0,sizeof(dp));dp[0][0]=1;
    for(re int i=1;i<=n;i++) {
        for(re int j=1;j<=m;j++) {
            memset(dp[o^1],0,sizeof(dp[o^1]));
            for(re int cur,k=0;k<=len;++k) {
                if(!dp[o][k]) continue;
                int left=k>>(j-1)&1,up=k>>j&1;
                if(!a[i][j]) {
                    if(!left&&!up) dp[o^1][k]+=dp[o][k];
                    continue;
                }
                if(!left&&!up) cur=k,upd(cur,j,1),upd(cur,j+1,1),dp[o^1][cur]+=dp[o][k];
                if(left&&up) cur=k,upd(cur,j,0),upd(cur,j+1,0),dp[o^1][cur]+=dp[o][k];
                if(left^up) {
                    cur=k;upd(cur,j,0),upd(cur,j+1,1);dp[o^1][cur]+=dp[o][k];
                    cur=k;upd(cur,j,1),upd(cur,j+1,0);dp[o^1][cur]+=dp[o][k];
                }
            }
            o^=1;
        }
        for(re int j=(1<<m)-1;j>=0;--j) dp[o][j<<1]=dp[o][j];
        for(re int j=0;j<=len;j++) if(j&1) dp[o][j]=0;
    }
    printf("%lld\n",dp[o][0]);
}
int main() {scanf("%d",&T);while(T--) solve();return 0;}

原文地址:https://www.cnblogs.com/asuldb/p/12106442.html

时间: 2024-08-03 03:13:35

HDU1693 Eat the Trees的相关文章

[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

【HDU1693】Eat the Trees(插头dp)

[HDU1693]Eat the Trees(插头dp) 题面 HDU Vjudge 大概就是网格图上有些点不能走,现在要找到若干条不相交的哈密顿回路使得所有格子都恰好被走过一遍. 题解 这题的弱化版本吧... 因为可以任意分配哈密顿回路的数量,因此根本不需要再考虑插头的配对问题了,那么直接分情况转移就好啦. #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #in

【HDU】1663 Eat the Trees

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1693 给出一块$r*c$的地,其中有的土地上种上了树,有些没有种上树,只能在种上树的地上走,通过走若干个回路,来走遍所有种树的土地.问有多少种走法. 插头DP. 既然可以走多个回路,似乎就不需要考虑括号序列合并的问题了,直接状压表示每一个位置有没有插头. 我写的转出. 1.如果当前点都没有上插头和左插头,那么插头无法延续,新建一个回路. 2.如果当前点都有上插头和左插头,回路在此处闭合. 3.如果上

[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

【HDU】1693 Eat the Trees

http://acm.hdu.edu.cn/showproblem.php?pid=1693 题意:n×m的棋盘求简单回路(可以多条)覆盖整个棋盘的方案,障碍格不许摆放.(n,m<=11) #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; struct H { static const int M=1000007;

Eat the Trees(hdu 1693)

题意:在n*m的矩阵中,有些格子有树,没有树的格子不能到达,找一条或多条回路,吃完所有的树,求有多少中方法. 第一道真正意义上的插头DP,可参考陈丹琦的<基于连通性状态压缩的动态规划问题>,虽然我看了一遍,但只是了解了个大概,主要还是看别人的代码,自己画图理解. 插头和轮廓线的定义就不说了,在PPT中很好理解. 先说一下转移的方式,如下图(p和q是当前枚举到的格子所面临的需要更新插头的地方): 通过在纸上画图,可以得出这么几个结论: 前一个状态的q和p都有插头的话,后一个状态的q和p都不能有插

HDU 1693 Eat the Trees

Problem Description Most of us know that in the game called DotA(Defense of the Ancient), Pudge is a strong hero in the first period of the game. When the game goes to end however, Pudge is not a strong hero any more.So Pudge’s teammates give him a n

HDU 1693 Eat the Trees (插头DP)

题意:给一个n*m的矩阵,为1时代表空格子,为0时代表障碍格子,问如果不经过障碍格子,可以画一至多个圆的话,有多少种方案?(n<12,m<12) 思路: 以一个非障碍格子为单位进行DP转移,所以可以用滚动数组.只需要保存m+1个插头的状态,其中有一个是右插头,其他都是下插头,若有插头的存在,该位为1,否则为0,初始时都是0. 需要考虑的是,(1)如果两个边缘都是插头,那么必须接上它们:(2)如果仅有一边是插头,则延续插头,可以有两个延续的方向(下和右):(3)如果都没有插头,那么必须另开两个新

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的过程是从左上角的点到右下