【插头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;
 10 const int MAX_S = 1000007;
 11
 12 struct node {
 13     int head[HASH], nxt[MAX_S];
 14     long long dp[MAX_S], st[MAX_S];
 15     int cnt;
 16     void init() {
 17         memset(head, -1, sizeof head);
 18         cnt = 0;
 19     }
 20     void push(long long s, long long v) {
 21         int now = s % HASH;
 22         for(int i = head[now]; ~i; i = nxt[i]) if(st[i] == s) {
 23                dp[i] += v;
 24             return ;
 25         }
 26         st[cnt] = s; dp[cnt] = v;
 27         nxt[cnt] = head[now];
 28         head[now] = cnt++;
 29     }
 30 }d[2];
 31
 32 int n, m;
 33
 34 int find_pos(long long s, int p) {
 35     return (s >> (p << 1)) & 3;
 36 }
 37
 38 void tp(long long &s, int p, long long v) {
 39     s &= (~(3ll << (p << 1)));
 40     s |= (v << (p << 1));
 41 }
 42
 43 int find_r(long long s, int p) {
 44     int cnt = 0;
 45     for(int i = p; i <= m; ++i) {
 46         if(find_pos(s, i) == 1) ++cnt;
 47         else if(find_pos(s, i) == 2) --cnt;
 48         if(!cnt) return i;
 49     }
 50 }
 51
 52 int find_l(long long s, int p) {
 53     int cnt = 0;
 54     for(int i = p; i >= 0; --i) {
 55         if(find_pos(s, i) == 2) ++cnt;
 56         else if(find_pos(s, i) == 1) --cnt;
 57         if(!cnt) return i;
 58     }
 59 }
 60
 61 void blank(int i, int j, int cur) {
 62     for(int k = 0; k < d[cur].cnt; ++k) {
 63         long long t = d[cur].st[k];
 64         int l = find_pos(t, j - 1), r = find_pos(t, j);
 65         if(l && r) {
 66             if(l == 1 && r == 1) {
 67                 int tpos = find_r(t, j);
 68                 tp(t, j - 1, 0); tp(t, j, 0); tp(t, tpos, 1);
 69                 d[cur ^ 1].push(t, d[cur].dp[k]);
 70             } else if(l == 2 && r == 1) {
 71                 tp(t, j - 1, 0); tp(t, j, 0);
 72                 d[cur ^ 1].push(t, d[cur].dp[k]);
 73             } else if(l == 2 && r == 2) {
 74                 int tpos = find_l(t, j - 1);
 75                 tp(t, j - 1, 0); tp(t, j, 0); tp(t, tpos, 2);
 76                 d[cur ^ 1].push(t, d[cur].dp[k]);
 77             } else { // 最后一个非障碍格子
 78                 tp(t, j - 1, 0); tp(t, j, 0);
 79                 d[cur ^ 1].push(t, d[cur].dp[k]);
 80             }
 81         } else if(l) {
 82             if(i < n) {
 83                 d[cur ^ 1].push(t, d[cur].dp[k]);
 84             }
 85             if(j < m) {
 86                 tp(t, j - 1, 0); tp(t, j, l);
 87                 d[cur ^ 1].push(t, d[cur].dp[k]);
 88             }
 89         } else if(r) {
 90             if(j < m) {
 91                 d[cur ^ 1].push(t, d[cur].dp[k]);
 92             }
 93             if(i < n) {
 94                 tp(t, j - 1, r); tp(t, j, 0);
 95                 d[cur ^ 1].push(t, d[cur].dp[k]);
 96             }
 97         } else { // 新建
 98             if(i < n && j < m) {
 99                 tp(t, j - 1, 1); tp(t, j, 2);
100                 d[cur ^ 1].push(t, d[cur].dp[k]);
101             }
102         }
103     }
104 }
105
106 void block(int i, int j, int cur) {
107     for (int k = 0; k < d[cur].cnt; ++k) {
108         long long t = d[cur].st[k];
109         int l = find_pos(t, j - 1), r = find_pos(t, j);
110         if (!l && !r) d[cur ^ 1].push(t, d[cur].dp[k]);
111     }
112 }
113
114 char str[17];
115 int a[MAX_N][MAX_M];
116
117 int main() {
118     int T;
119     scanf("%d", &T);
120     int cas = 0;
121     while (T-- > 0) {
122         scanf("%d%d", &n, &m);
123         memset(a, 0, sizeof a);
124         for (int i = 1; i <= n; ++i) {
125             for (int j = 1; j <= m; ++j) {
126                 scanf("%d", &a[i][j]);
127             }
128         }
129         long long ans = 0;
130         int cur = 0;
131         d[cur].init();
132         d[cur].push(0, 1);
133         for (int i = 1; i <= n; ++i) {
134             for (int j = 1; j <= m; ++j) {
135                 d[cur ^ 1].init();
136                 if (a[i][j]) blank(i, j, cur);
137                 else block(i, j, cur);
138                 cur ^= 1;
139             }
140             for (int j = 0; j < d[cur].cnt; ++j)
141                 d[cur].st[j] <<= 2;
142         }
143         for (int i = 0; i < d[cur].cnt; ++i)
144             ans += d[cur].dp[i];
145         printf("Case %d: There are %I64d ways to eat the trees.\n", ++cas, ans);
146     }
147     return 0;
148 }

时间: 2024-08-01 22:46:58

【插头DP】HDU 1693 Eat the Trees的相关文章

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

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的矩阵,为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

[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

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

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;

状态压缩插头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表示无插头.如果是

插头DP专题

建议入门的人先看cd琦的<基于连通性状态压缩的动态规划问题>.事半功倍. 插头DP其实是比较久以前听说的一个东西,当初是水了几道水题,最近打算温习一下,顺便看下能否入门之类. 插头DP建议先理解“插头”的概念.然后会HASH表(这个其实是很基础的东西,应该都会的).然后就是DP. 以及特殊题目的特殊处理. 好像一般是求N,M<=12的网格图的某种回路数或某种通路数的方案数. 大体上每个题说几句特殊处理,有问题请纠正....题目的顺序基本上难度递增 另外代码我都是用括号匹配的.因为感觉连通