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), 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 new assignment—Eat the Trees!

The trees are in a rectangle N * M cells in size and each of the cells either has exactly one tree or has nothing at all. And what Pudge needs to do is to eat all trees that are in the cells.

There are several rules Pudge must follow:

I. Pudge must eat the trees by choosing a circuit and he then will eat all trees that are in the chosen circuit.

II. The cell that does not contain a tree is unreachable, e.g. each of the cells that is through the circuit which Pudge chooses must contain a tree and when the circuit is chosen, the trees which are in the cells on the circuit will disappear.

III. Pudge may choose one or more circuits to eat the trees.

Now Pudge has a question, how many ways are there to eat the trees?

At the picture below three samples are given for N = 6 and M = 3(gray square means no trees in the cell, and the bold black line means the chosen circuit(s))

Input

The input consists of several test cases. The first line of the input is the number of the cases. There are no more than 10 cases.

For each case, the first line contains the integer numbers N and M, 1<=N, M<=11. Each of the next N lines contains M numbers (either 0 or 1) separated by a space. Number 0 means a cell which has no trees and number 1 means a cell that has exactly one tree.

Output

For each case, you should print the desired number of ways in one line. It is guaranteed, that it does not exceed 263 – 1. Use the format in the sample.

Sample Input

2
6 3
1 1 1
1 0 1
1 1 1
1 1 1
1 0 1
1 1 1
2 4
1 1 1 1
1 1 1 1

Sample Output

Case 1: There are 3 ways to eat the trees.
Case 2: There are 2 ways to eat the trees.

Source

2008 “Sunline Cup” National Invitational Contest

题意:

给n*m的方格,有些方格有障碍,问有多少种方式能使所有的非障碍点都在某个环上,环可以有多个。

思路:

插头dp入门,按照点来转移,dp[i][j][k]表示到i行j列的时候,轮廓线上的插头状态为k时候的种类数,有6中情况,划一划就能知道怎样转移了,注意行与行之间单独转移,每行末尾不能有右插头。

感想:

dp如此之菜,插头dp就先放放了,先把其他的搞好,到一定阶段了再来学习吧。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#define maxn 205
#define MAXN 100005
#define mod 100000000
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-8
typedef long long ll;
using namespace std;

ll n,m,ans,cnt,tot,flag;
ll mp[12][12],dp[12][12][1<<12];

void solve()
{
    ll i,j,k,t;
    ll up,down,left,right;
    tot=(1<<m+1)-1;
    memset(dp,0,sizeof(dp));
    dp[0][m][0]=1;
    for(i=1;i<=n;i++)
    {
        for(k=0;k<(1<<m);k++) // 行与行之间单独转移
        {
            dp[i][0][k<<1]=dp[i-1][m][k];
        }
        for(j=1;j<=m;j++)
        {
            for(k=0;k<=tot;k++) // i j-1的状态
            {
                if(dp[i][j-1][k]==0) continue ;
                down=left=1<<j-1;
                right=up=1<<j;
                if(mp[i][j])
                {
                    if((k&left)&&(k&up))  // 两个插头
                    {
                        dp[i][j][k^left^up]+=dp[i][j-1][k];
                    }
                    else if(!(k&left)&&!(k&up)) // 0个插头
                    {
                        dp[i][j][k^left^up]+=dp[i][j-1][k];
                    }
                    else // 一个插头
                    {
                        dp[i][j][k]+=dp[i][j-1][k];
                        dp[i][j][k^left^up]+=dp[i][j-1][k];
                    }
                }
                else
                {
                    if(!(k&left)&&!(k&up)) dp[i][j][k]+=dp[i][j-1][k];
                }
            }
        }
    }
    ans=dp[n][m][0];
}
int main()
{
    ll i,j,t,test=0;
    scanf("%I64d",&t);
    while(t--)
    {
        scanf("%I64d%I64d",&n,&m);
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=m;j++)
            {
                scanf("%I64d",&mp[i][j]);
            }
        }
        solve();
        printf("Case %I64d: There are %I64d ways to eat the trees.\n",++test,ans);
    }
    return 0;
}

hdu 1693 Eat the Trees (插头dp入门)

时间: 2024-10-15 12:29:48

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

[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

【插头DP】HDU 1693 Eat the Trees

通道:http://acm.hdu.edu.cn/showproblem.php?pid=1693 题意:多回路路径方案数,无障碍. 代码: 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 5 using namespace std; 6 7 const int MAX_N = 13; 8 const int MAX_M = 13; 9 const int HASH = 10007; 1

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)

题目大意:要求你将所有非障碍格子都走一遍,形成回路(可以多回路),问有多少种方法 解题思路: 参考基于连通性状态压缩的动态规划问题 - 陈丹琦 以下为代码 #include<cstdio> #include<algorithm> #include<cstring> using namespace std; #define N 12 #define S (1 << 12) int n, m; long long dp[N][N][S]; int cas = 1

[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

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 4804 Campus Design(插头DP)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4804 题意:给定一个图,0是不能放的,然后现在有1X1和1X2方块,最后铺满该图,使得1X1使用次数在C到D之间,1X2次数随便,问有几种放法 思路:插头DP的变形,只要多考虑1X1的情况即可,然后DP多开一维表示使用1X1的个数 代码: #include <stdio.h> #include <string.h> #include <algorithm> #include

【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;