hdu 1693 : Eat the Trees 【插头dp 入门】
题意: 给出一个n*m大小的01矩阵,在其中画线连成封闭图形,其中对每一个值为1的方格,线要恰好穿入穿出共两次,对每一个值为0的方格,所画线不能经过。
参考资料: 《基于连通性状态压缩的动态规划问题》 ——陈丹琦 2008年国家集训队论文
递推过程中,按照 遍历行->遍历行上每一格->遍历 “轮廓线跨过该格时所有可能的状态变化” 的顺序
这样复杂度是 O(n*m*2m+1) (m+1是因为轮廓线上有m个单元是与列数对应的,另有一单独的竖线单元)
问题关键点在于解决 “轮廓线跨过该格时所有可能的状态变化”
首先是由第i行到第i+1行的递推关系。显然,第i+1行上,轮廓线未跨过任何方格,与在第i行,轮廓线跨过了所有方格,这两者轮廓线的形态是相同的,不过,前者的状态state1应表示为后者的状态state2<<1,在代码中,计数关系通过 for(int k=0;k<M;k++) dp[i][0][k<<1]=dp[i-1][m][k]; 来实现。
然后是在同一行上跨过某一格时的递推关系。不考虑方格值为0,这道题里面共有四种情况,对于具体某一格而言,即 00->11,01->10,10->01,11->00。对于方格值为0的情况,显然只能是00->00。
后继状态总计数=sigma合法的前驱状态。
具体可以借助代码来理解
#include<bits/stdc++.h>
using namespace std;
typedef long long LL; const int maxn=; int n,m;
int mp[maxn][maxn];
LL dp[maxn][maxn][<<maxn]; LL solve()
{
int M=<<(m+); //轮廓线上状态总数
dp[][m][]=;
for(int i=;i<=n;i++) //遍历行
{
for(int k=;k<M;k++)
dp[i][][k<<]=dp[i-][m][k];
for(int j=;j<=m;j++) //j用来指示轮廓线中小竖线的位置
{
int state1=(<<j),state2=(<<(j-));
for(int k=;k<M;k++)
{
if(mp[i][j])
{
if((k&state1)==&&(k&state2)==)
dp[i][j][k]=dp[i][j-][k+state1+state2];
else if((k&state1)!=&&(k&state2)!=)
dp[i][j][k]=dp[i][j-][k-state1-state2];
else if((k&state1)==&&(k&state2)!=)
{
dp[i][j][k]+=dp[i][j-][k-state2+state1];
dp[i][j][k]+=dp[i][j-][k];
}
else
{
dp[i][j][k]+=dp[i][j-][k-state1+state2];
dp[i][j][k]+=dp[i][j-][k];
}
}
else
if((k&state1)==&&(k&state2)==)
dp[i][j][k]=dp[i][j-][k];
}
}
}
return dp[n][m][];
} int main()
{
int T,kase=;
scanf("%d",&T);
while(T--)
{
memset(dp,,sizeof(dp));
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
scanf("%d",&mp[i][j]);
printf("Case %d: There are %lld ways to eat the trees.\n",++kase,solve());
}
}
hdu 1693 : Eat the Trees 【插头dp 入门】的更多相关文章
- hdu 1693 Eat the Trees——插头DP
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1693 第一道插头 DP ! 直接用二进制数表示状态即可. #include<cstdio> # ...
- HDU 1693 Eat the Trees ——插头DP
[题目分析] 吃树. 直接插头DP,算是一道真正的入门题目. 0/1表示有没有插头 [代码] #include <cstdio> #include <cstring> #inc ...
- HDU 1693 Eat the Trees(插头DP)
题目链接 USACO 第6章,第一题是一个插头DP,无奈啊.从头看起,看了好久的陈丹琦的论文,表示木看懂... 大体知道思路之后,还是无法实现代码.. 此题是插头DP最最简单的一个,在一个n*m的棋盘 ...
- hdu1693 Eat the Trees [插头DP经典例题]
想当初,我听见大佬们谈起插头DP时,觉得插头DP是个神仙的东西. 某大佬:"考场见到插头DP,直接弃疗." 现在,我终于懂了他们为什么这么说了. 因为-- 插头DP很毒瘤! 为什么 ...
- HDU 1693 Eat the Trees(插头DP,入门题)
Problem Description Most of us know that in the game called DotA(Defense of the Ancient), Pudge is a ...
- HDU 1693 Eat the Trees(插头DP、棋盘哈密顿回路数)+ URAL 1519 Formula 1(插头DP、棋盘哈密顿单回路数)
插头DP基础题的样子...输入N,M<=11,以及N*M的01矩阵,0(1)表示有(无)障碍物.输出哈密顿回路(可以多回路)方案数... 看了个ppt,画了下图...感觉还是挺有效的... 参考 ...
- HDU - 1693 Eat the Trees(多回路插头DP)
题目大意:要求你将全部非障碍格子都走一遍,形成回路(能够多回路),问有多少种方法 解题思路: 參考基于连通性状态压缩的动态规划问题 - 陈丹琦 下面为代码 #include<cstdio> ...
- HDU 1693 Eat the Trees (插头DP)
题意:给一个n*m的矩阵,为1时代表空格子,为0时代表障碍格子,问如果不经过障碍格子,可以画一至多个圆的话,有多少种方案?(n<12,m<12) 思路: 这题不需要用到最小表示法以及括号表 ...
- HDU 1693 Eat the Trees
第一道(可能也是最后一道)插头dp.... 总算是领略了它的魅力... #include<iostream> #include<cstdio> #include<cstr ...
随机推荐
- Python分析《武林外传》 -----转载
转载原链接:http://www.cnblogs.com/fredkeke/p/8328387.html 我一向比较喜欢看武侠电影.小说,但是06年武林外传开播的时候并没有追剧,简单扫几眼之后发现他们 ...
- Redis 简介,安装,卸载
一.Redis简介 redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(s ...
- C++ STL 二分查找
转载自 https://www.cnblogs.com/Tang-tangt/p/9291018.html 二分查找的函数有 3 个: 参考:C++ lower_bound 和upper_bound ...
- Oracle编程艺术--配置环境
如何设置login.sql,参照了本书作者的意见,我也大概弄明白了 只是该文件的存放位置一直就出错,百度了很久,说是$ORACLE_HOME/sqlplus/admin/glogin.sql(默认)于 ...
- Arrays.toList工具类
- 测开之路一百:jquery引用、语法、事件
工作中一般会使用jquery代替js,jquery官网:https://jquery.com/ 引用jquery: 第一种方式:下载引用: jquery下载官网:https://jquery.com/ ...
- django-xadmin常用内容记录
自定义菜单名称: 1 修改app下的 apps.py文件 添加 class OperationConfig(AppConfig): name = 'operation' verbose_name = ...
- Spring Boot系列(四) Spring Cloud 之 Config Client
Config 是通过 PropertySource 提供. 这节的内容主要是探讨配置, 特别是 PropertySource 的加载机制. Spring Cloud 技术体系 分布式配置 服务注册/发 ...
- PTA第四周作业
一.本周完成的作业 7-2 选择法排序 (20 分) 本题要求将给定的n个整数从大到小排序后输出. 输入格式: 输入第一行给出一个不超过10的正整数n.第二行给出n个整数,其间以空格分隔. 输出格式: ...
- node.js—创建、删除、追加文件等方法汇总
使用Node.js的fs模块必须在electron项目里 /* 1. fs.stat 检测是文件还是目录(目录 文件是否存在) 2. fs.mkdir 创建目录 (创建之前先判断是否存在) 3. fs ...