题目链接

hdu1693

题解

插头\(dp\)

特点:范围小,网格图,连通性

轮廓线:已决策点和未决策点的分界线

插头:存在于网格之间,表示着网格建的信息,此题中表示两个网格间是否连边

状态表示:当前点\((i,j)\)和轮廓线上\(m + 1\)个插头的状态

状态转移:



我们用\(f[i][j][s]\)表示如上的状态,最后一次决策点为\((i,j)\),轮廓线上插头状态为\(s\)的方案数

比如上图\(s = 1101001\)

之后我们扩展新的点,枚举它插头的状态进行转移



在本题中,要使最终形成若干回路,每个点度数必须为\(2\),所以我们扩展点的时候记录它已有的插头数,然后剩余的插头数就可以唯一确定

然后就可以\(O(nm2^m)\)过了这道插头\(dp\)入门题

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
using namespace std;
const int maxn = 12,maxm = 100005,INF = 1000000000;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
int n,m,S[maxn][maxn];
LL f[maxn][maxn][1 << maxn];
void work(int C){
cls(f);
if (!S[1][1]) f[1][1][0] = 1;
else {
if (S[1][2] == 0 || S[2][1] == 0){
printf("Case %d: There are 0 ways to eat the trees.\n",C);
return;
}
f[1][1][3] = 1;
}
int maxv = (1 << m + 1) - 1,cnt,e,t;
for (int i = 1; i <= n; i++){
for (int j = 1; j <= m; j++){
if (i == n && j == m) break;
for (int s = 0; s <= maxv; s++){
if (!f[i][j][s]) continue;
if (j == m){
if (s & 1){
if (i + 2 <= n && S[i + 2][1])
f[i + 1][1][(s >> 1) << 2 | 1] += f[i][j][s];
if (S[i + 1][2])
f[i + 1][1][(s >> 1) << 2 | 2] += f[i][j][s];
}
else {
if (!S[i + 1][1]) f[i + 1][1][(s >> 1) << 2] += f[i][j][s];
else {
if (i + 2 > n || !S[i + 2][1] || !S[i + 1][2]) continue;
f[i + 1][1][(s >> 1) << 2 | 3] += f[i][j][s];
}
}
}
else {
cnt = ((s >> j) & 1) + ((s >> j + 1) & 1);
t = (s >> j) & 3; e = s ^ (t << j);
if (cnt && !S[i][j + 1]) continue;
if (cnt == 2) f[i][j + 1][e] += f[i][j][s];
else if (cnt == 1){
if (i + 1 <= n && S[i + 1][j + 1])
f[i][j + 1][e | (1 << j)] += f[i][j][s];
if (j + 2 <= m && S[i][j + 2])
f[i][j + 1][e | (1 << j + 1)] += f[i][j][s];
}
else {
if (!S[i][j + 1]) f[i][j + 1][e] += f[i][j][s];
else {
if (i + 1 > n || j + 2 > m || !S[i + 1][j + 1] || !S[i][j + 2])
continue;
f[i][j + 1][e | (3 << j)] += f[i][j][s];
}
}
}
}
}
}
LL ans = 0;
for (int s = 0; s <= maxv; s++)
ans += f[n][m][s];
printf("Case %d: There are %lld ways to eat the trees.\n",C,ans);
}
int main(){
int T = read();
REP(t,T){
n = read(); m = read();
REP(i,n) REP(j,m) S[i][j] = read();
if (n == 1 || m == 1){
if (!S[n][m]) printf("Case %d: There are 1 ways to eat the trees.\n",t);
else printf("Case %d: There are 0 ways to eat the trees.\n",t);
continue;
}
work(t);
}
return 0;
}

hdu1693 Eat the Trees 【插头dp】的更多相关文章

  1. HDU1693 Eat the Trees —— 插头DP

    题目链接:https://vjudge.net/problem/HDU-1693 Eat the Trees Time Limit: 4000/2000 MS (Java/Others)    Mem ...

  2. HDU1693 Eat the Trees 插头dp

    原文链接http://www.cnblogs.com/zhouzhendong/p/8433484.html 题目传送门 - HDU1693 题意概括 多回路经过所有格子的方案数. 做法 最基础的插头 ...

  3. hdu1693 Eat the Trees [插头DP经典例题]

    想当初,我听见大佬们谈起插头DP时,觉得插头DP是个神仙的东西. 某大佬:"考场见到插头DP,直接弃疗." 现在,我终于懂了他们为什么这么说了. 因为-- 插头DP很毒瘤! 为什么 ...

  4. HDU 1693 Eat the Trees(插头DP)

    题目链接 USACO 第6章,第一题是一个插头DP,无奈啊.从头看起,看了好久的陈丹琦的论文,表示木看懂... 大体知道思路之后,还是无法实现代码.. 此题是插头DP最最简单的一个,在一个n*m的棋盘 ...

  5. hdu 1693 Eat the Trees——插头DP

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1693 第一道插头 DP ! 直接用二进制数表示状态即可. #include<cstdio> # ...

  6. HDU 1693 Eat the Trees ——插头DP

    [题目分析] 吃树. 直接插头DP,算是一道真正的入门题目. 0/1表示有没有插头 [代码] #include <cstdio> #include <cstring> #inc ...

  7. hdu1693:eat trees(插头dp)

    题目大意: 题目背景竟然是dota!屠夫打到大后期就没用了,,只能去吃树! 给一个n*m的地图,有些格子是不可到达的,要把所有可到达的格子的树都吃完,并且要走回路,求方案数 题解: 这题大概是最简单的 ...

  8. [Hdu1693]Eat the Trees(插头DP)

    Description 题意:在n*m(1<=N, M<=11 )的矩阵中,有些格子有树,没有树的格子不能到达,找一条或多条回路,吃完所有的树,求有多少种方法. Solution 插头DP ...

  9. 2019.01.23 hdu1693 Eat the Trees(轮廓线dp)

    传送门 题意简述:给一个有障碍的网格图,问用若干个不相交的回路覆盖所有非障碍格子的方案数. 思路:轮廓线dpdpdp的模板题. 同样是讨论插头的情况,只不过没有前一道题复杂,不懂的看代码吧. 代码: ...

随机推荐

  1. 说说ejabberd 离线消息的坑

    使用过ejabberd的或许知道,也许踩过这个坑.那么就说说我们踩过的ejabberd的离线消息的坑吧. ejabberd原生的离线消息的机制是,一般用户保存100条离线消息,管理员保存5000条离线 ...

  2. java 多路分发

    1.概念 一个函数处理多种类型,其实和多态差不多. 但是要处理两种或者多种类型的数据时,就需要判断每种类型以及每种类型所对应的处理.(PS:我只是在走别人的老路,网上一搜这种概念,博客一大堆,我不知道 ...

  3. jmeter逻辑控制器

    刚开始学习,只写几种了解的逻辑控制器 1.简单控制器 只用来组合采样器和其他逻辑控制器,不影响jmeter的运行 2.循环控制器 用来循环执行采样器和其他逻辑控制器,例如一个用户发送特定请求多次,即可 ...

  4. kubeadm构建k8s之Prometheus-operated监控(0.18.1)

    介绍: 大家好,k8s的搭建有许多方式,也有许多快速部署的,为了简化部署的复杂度,官方也提供了开源的kubeadm快速部署,最新1.10.x版本已经可以实现部署集群, 如果你对k8s的原理已经非常了解 ...

  5. Halcon学习网

    重码网是一个在线机器视觉学习网站,推出了Halcon,Visionpro机器视觉学习视频教程,视频内容通俗易懂,没有编程基础的同学,照着视频练习,也同样可以学会. 学机器视觉,拿高薪,成就技术大拿.重 ...

  6. Bin Packing 装箱问题——NPH问题的暴力枚举 状压DP

    题目: 给定n(1≤n≤24)个物品,重量分别为wi,装进一些容量为S(S<1e8)的背包,最少需要多少个背包?

  7. WEB前端开发流程总结

    作者声明:本博客中所写的文章,都是博主自学过程的笔记,参考了很多的学习资料,学习资料和笔记会注明出处,所有的内容都以交流学习为主.有不正确的地方,欢迎批评指正 WEB前端开发项目流程总结 1.新建项目 ...

  8. c# dataGridView排序

    一.对阿拉伯数字进行自定义排序: 简单有效方法: 1.该列的sortmode属性为auto...(一般默认) 2.比如首列序号,添加该列数据的时候直接添加int即可.切忌不要用string. obje ...

  9. RIGHT-BICEP测试第二次程序

    根据Right-BICEP单元测试的方法我对我写的第二次程序进行了测试: 测试一:测试能否控制使用乘除 测试二:测试是否能加括号 测试三:是否可以控制题目输出数量 测试四:能否控制输出方式,选择文件输 ...

  10. CS小分队第二阶段冲刺站立会议(5月26日)

    昨天成果:对扫雷进行了全面的优化,增加了特色皮肤,为其添加了游戏音效,并且做出了换肤的接口. 今日计划:应队友要求对抽号倒计时器进行分离,修改界面结构以便美化. 遇到问题:扫雷的界面美化比较困难,自动 ...