HDU 1693 Eat the Trees (插头DP)
题意:给一个n*m的矩阵,为1时代表空格子,为0时代表障碍格子,问如果不经过障碍格子,可以画一至多个圆的话,有多少种方案?(n<12,m<12)
思路:
这题不需要用到最小表示法以及括号表示法。
以一个非障碍格子为单位进行DP转移,所以可以用滚动数组。只需要保存m+1个插头的状态,其中有一个是右插头,其他都是下插头,若有插头的存在,该位为1,否则为0,初始时都是0。
需要考虑的是,(1)如果两个边缘都是插头,那么必须接上它们;(2)如果仅有一边是插头,则延续插头,可以有两个延续的方向(下和右);(3)如果都没有插头,那么必须另开两个新插头(新连通分量)。
如下图,记录的状态是:101111。由于是按行来保存状态的,第一个格子需要特殊考虑,将所有状态左移一位,最后的一位就是右方向的边缘。假设上行都有下插头,那么此行初始时是011111,可以看到最左边的是0,表示无右插头,注意:我是按照111110保存的,即最低位是最左边。

初始格子dp[0][0]=1,而答案就是dp[cur][0]了,肯定是无插头存在的状态了,所有的圆圈都是完整的。
#include <bits/stdc++.h>
#define pii pair<int,int>
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
const int N=;
int g[N][N], cur;
LL dp[N][<<N]; void clear()
{
cur^=;
memset(dp[cur], , sizeof(dp[cur]));
} LL cal(int n,int m)
{
dp[][]=; //开始时没有任何插头
for(int i=; i<n; i++) //枚举格子
{
clear();
for(int k=; k<(<<m); k++) dp[cur][k<<]+=dp[cur^][k]; //最高位自动会被忽略
for(int j=; j<m; j++)
{
int r=(<<j), d=(<<(j+)); //r和d 相当于 右和下
clear();
for(int k=; k<(<<(m+)); k++) //枚举状态
{
if(g[i][j]) //空格
{
if( (k&r) && (k&d) ) //两边都有插头:连起来,变无插头
dp[cur][k^r^d]+=dp[cur^][k];
else if( k&r || k&d ) //其中一边有插头:可转两个方向
{
dp[cur][k]+=dp[cur^][k];
dp[cur][k^r^d]+=dp[cur^][k];
}
else //无插头:另开两个新插头
dp[cur][k|r|d]=dp[cur^][k];
}
else //障碍格子
{
if( !(k&r) && !(k&d) )
dp[cur][k]=dp[cur^][k];
}
}
}
}
return dp[cur][];
} int main()
{
//freopen("input.txt", "r", stdin);
int n, m, t, Case=;
cin>>t;
while(t--)
{
scanf("%d%d",&n,&m);
memset(g, , sizeof(g));
memset(dp, , sizeof(dp));
for(int i=; i<n; i++)
for(int j=; j<m; j++)
scanf("%d",&g[i][j]);
printf("Case %d: There are %lld ways to eat the trees.\n", ++Case, cal(n,m));
}
return ;
}
AC代码
最小表示法实现:
#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#define pii pair<int,int>
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
const int N=;
int g[N][N], n, m, cur, code[N];
struct Hash_Map
{
static const int mod=;
static const int NN=;
int head[mod]; //桶指针
int next[NN]; //记录链的信息
LL status[NN]; //状态
LL value[NN]; //状态对应的DP值。
int size; void clear()
{
memset(head, -, sizeof(head));
size = ;
} void insert(LL st, LL val)
{
int h = st%mod;
for(int i=head[h]; i!=-; i=next[i])
{
if(status[i] == st)
{
value[i] += val;
return ;
}
}
status[size]= st;
value[size] = val;
next[size] = head[h] ;
head[h] = size++;
}
}hashmap[]; void decode(LL s)
{
for(int i=; i<=m; i++)
{
code[i]=s&;
s>>=;
}
}
int cnt[N];
LL encode()
{
LL s=;
memset(cnt, -, sizeof(cnt));
cnt[]=;
for(int i=m,up=; i>=; i--)
{
if(cnt[code[i]]==-) cnt[code[i]]=++up;
code[i]=cnt[code[i]];
s<<=;
s|=code[i];
}
return s;
} void DP(int i,int j)
{
for(int k=; k<hashmap[cur^].size; k++)
{
decode(hashmap[cur^].status[k]);
LL v=hashmap[cur^].value[k]; int R=code[j], D=code[j+]; if(g[i][j]==)
{
if(R==&&D==) hashmap[cur].insert(encode(),v);
continue;
} if(R&&D)
{
code[j]=code[j+]=;
if(R==D) hashmap[cur].insert(encode(),v);
else
{
for(int r=; r<=m; r++)
if(code[r]==R) code[r]=D;
hashmap[cur].insert(encode(), v);
}
}
else if(R||D)
{
R+=D;
if(i+<n)
{
code[j]=R;
code[j+]=;
hashmap[cur].insert(encode(), v);
}
if(j+<m)
{
code[j]=;
code[j+]=R;
hashmap[cur].insert(encode(), v);
}
}
else
{
code[j]=;
code[j+]=;
if(i+<n && j+<m) hashmap[cur].insert(encode(), v);
}
}
} void cal()
{
cur=;
hashmap[cur].clear();
hashmap[cur].insert(,);
for(int i=; i<n; i++)
{
for(int j=; j<hashmap[cur].size; j++) hashmap[cur].status[j]<<=;
for(int j=; j<m; j++)
{
hashmap[cur^=].clear();
DP(i,j);
//cout<<hashmap[cur].size<<endl;
}
}
} LL print()
{
for(int i=; i<hashmap[cur].size; i++)
if(hashmap[cur].status[i]==)
return hashmap[cur].value[i];
return ;
} int main()
{
//freopen("input.txt", "r", stdin);
int t, Case=;
cin>>t;
while(t--)
{
scanf("%d%d",&n,&m);
for(int i=; i<n; i++)
{
for(int j=; j<m; j++)
{
scanf("%d",&g[i][j]);
}
}
cal();
printf("Case %d: There are %lld ways to eat the trees.\n", ++Case, print());
}
}
AC代码
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)
题目链接 USACO 第6章,第一题是一个插头DP,无奈啊.从头看起,看了好久的陈丹琦的论文,表示木看懂... 大体知道思路之后,还是无法实现代码.. 此题是插头DP最最简单的一个,在一个n*m的棋盘 ...
- HDU 1693 Eat the Trees ——插头DP
[题目分析] 吃树. 直接插头DP,算是一道真正的入门题目. 0/1表示有没有插头 [代码] #include <cstdio> #include <cstring> #inc ...
- hdu1693 Eat the Trees [插头DP经典例题]
想当初,我听见大佬们谈起插头DP时,觉得插头DP是个神仙的东西. 某大佬:"考场见到插头DP,直接弃疗." 现在,我终于懂了他们为什么这么说了. 因为-- 插头DP很毒瘤! 为什么 ...
- 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,入门题)
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 入门】
题目链接 题意: 给出一个n*m大小的01矩阵,在其中画线连成封闭图形,其中对每一个值为1的方格,线要恰好穿入穿出共两次,对每一个值为0的方格,所画线不能经过. 参考资料: <基于连通性状态压缩 ...
- HDU 1693 Eat the Trees
第一道(可能也是最后一道)插头dp.... 总算是领略了它的魅力... #include<iostream> #include<cstdio> #include<cstr ...
随机推荐
- _beginThreadex的用法
http://blog.csdn.net/cjcy1984001/article/details/6675669 线程开始和停止函数! unsigned long _beginthreadex( v ...
- UVa 1631 Locker (DP)
题意:有一个 n 位密码锁,每位都是0-9,可以循环旋转.同时可以让1-3个相邻数字进行旋转一个,给定初始状态和目状态,问你最少要转多少次. 析:很明显的一个DP题.dp[i][j][k] 表示前 i ...
- liteos任务(二)
任务 1 基本概念 从系统的角度看,任务是竞争系统资源的最小运行单元.任务可以使用或等待CPU.使用内存空间等系统资源,并独立于其它任务运行. Huawei LiteOS的任务模块可以给用户提供多个任 ...
- Codeforces - 65D - Harry Potter and the Sorting Hat - 简单搜索
https://codeforces.com/problemset/problem/65/D 哈利波特!一种新思路的状压记忆化dfs,记得每次dfs用完要减回去.而且一定是要在dfs外部进行加减!防止 ...
- BlocksKit的使用
一.引言 众所周知Block已被广泛用于iOS编程.它们通常被用作可并发执行的逻辑单元的封装,或者作为事件触发的回调.Block比传统回调函数有2点优势: 允许在调用点上下文书写执行逻辑,不用分离函数 ...
- BackgroundWorker的使用一二(可视化编程,开始后台工作,报告进度,取消后台工作等)
C# 提供了BackgroundWorker功能非常强大,可以将某项工作放到后台运行,可以让后台报告进度,可以取消后台工作...... BackgroundWorker的上述功能是通过 1. 三个主要 ...
- 2019最好用的自动化测试工具Top 10,果断收藏!
经常有人在公众号留言或是后台问我,做自动化测试用哪个工具好,或是学哪门编程语言好呢? 这个时候总是无奈的说: 你应该学习Python 或是Java. 你应该掌握Selenium. 又或者你需要学会jm ...
- Maven - settings.xml简易配置Demo
前言 这里贴一下settings.xml的一个简易配置demo,就是简单配置了:本地的仓库地址.阿里云镜像.指定使用jdk1.8进行编译. 这里使用的Maven是3.5.0版本的. 配置文件demo ...
- 根据select中选定option触发不同事件
做公司项目,要实现一个小需求,根据下拉框选定的数据,绑定不同的事件.我的思路是获取select下面的option值,然后给它们定义不同的点击事件,但是在使用中option不能添加类,同时没有click ...
- 最大xor,and,or
http://210.33.19.103/contest/998 and,or部分 并不用01trie,题目&题解:https://blog.csdn.net/dreaming__ldx/ar ...