hdu1693:eat trees(插头dp)

题目大意:

题目背景竟然是dota!屠夫打到大后期就没用了,,只能去吃树!

给一个n*m的地图,有些格子是不可到达的,要把所有可到达的格子的树都吃完,并且要走回路,求方案数

题解:

这题大概是最简单的插头dp了。。

比陈丹琦论文里的例题还要简单,因为允许有多个回路,所以不需要存储插头之间的连通性,直接二进制状压

搞清楚插头和轮廓线的概念基本就可以做出来了

这里有一些资料http://www.docin.com/p-741918386.html

代码:

#include <iostream>
#include <stdio.h>
#include<string.h>
#include<algorithm>
#include<string>
#include<ctype.h>
using namespace std;
#define MAXN 10000
long long dp[13][13][1<<13];
int g[13][13];
int n,m;
int main()
{
    int t,cas=0;
    scanf("%d",&t);
    while(t--)
    {
        cas++;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                scanf("%d",g[i]+j);
            }
        }
        memset(dp,0,sizeof(dp));
        dp[0][m][0]=1;
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<(1<<m);j++)
            {
                dp[i][0][j<<1]=dp[i-1][m][j];
            }
            for(int j=1;j<=m;j++)
            {
                for(int k=0;k<(1<<(m+1));k++)
                {
                    int u=1<<j;
                    int l=1<<(j-1);
                    if(g[i][j]==0)
                    {
                        if((!(k&u))&&(!(k&l)))
                            dp[i][j][k]=dp[i][j-1][k];
                        continue;
                    }
                    if((k&u)&&(k&l))
                    {
                        dp[i][j][k-u-l]+=dp[i][j-1][k];
                    }
                    if((k&u)&&(!(k&l)))
                    {
                        dp[i][j][k]+=dp[i][j-1][k];
                        dp[i][j][k-u+l]+=dp[i][j-1][k];
                    }
                    if((k&l)&&(!(k&u)))
                    {
                        dp[i][j][k]+=dp[i][j-1][k];
                        dp[i][j][k-l+u]+=dp[i][j-1][k];
                    }
                    if((!(k&u))&&(!(k&l)))
                    {
                        dp[i][j][k+u+l]+=dp[i][j-1][k];
                    }
                }
            }
        }
        printf("Case %d: There are %I64d ways to eat the trees.\n",cas,dp[n][m][0]);
    }
    return 0;
}
时间: 2024-08-29 05:53:30

hdu1693:eat trees(插头dp)的相关文章

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 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 1693 Eat the Trees (插头dp入门)

Eat the Trees Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2507    Accepted Submission(s): 1225 Problem Description Most of us know that in the game called DotA(Defense of the Ancient), Pudg

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

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

hdu1693插头dp(多回路)

题意:在n*m的矩阵中,有些格子有树,没有树的格子不能到达,找一条或多条回路,吃全然部的树,求有多少中方法. 这题是插头dp,刚刚学习,不是非常熟悉,研究了好几天才明确插头dp的方法,他们老是讲一些什么轮廓线啊,插头啊什么的,刚開始全然不知道这些事干什么的,看完cdq的大作后也是一头的雾水,看代码,绘图,一步一步的推,最终明确了,那个是为什么,这里讲一讲. 轮廓线表示的是当前插头的状态,这题中状态中1表示有插头,0表示无插头,假设是横线的话就是上面的格子与以下的格子相连的状态,这题中显然一个格子

hdu1693 插头dp

题意:给了一个矩阵图,要求使用回路把图中的树全部吃掉的方案树,没有树的点不能走,吃完了这个点也就没有了,走到哪吃到哪 用插头dp搞 #include <iostream> #include <algorithm> #include <cstdio> #include <vector> #include <string.h> using namespace std; typedef long long LL; int G[11][11]; int

HDU1693 Eat the Trees

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

初探插头dp

开学那个月学了点新东西,不知道还记不记得了,mark一下 感觉cdq的论文讲的很详细 题主要跟着kuangbin巨做了几道基础的 http://www.cnblogs.com/kuangbin/archive/2012/10/02/2710343.html 还有几道没做,留着坑 感觉广义括号表示法虽然神奇,但一般最小表示法就够用了吧,感觉最小表示法更直观一点 hdu1693 1 #include<cstdio> 2 #include<iostream> 3 #include<