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 ...
随机推荐
- 安装ubuntu+Windows双系统, Windows启动项消失
这里主要介绍grub分区损坏的问题: 首先介绍最简单的方法, 不确定能不能成功, 但是最好先用此方法, 毕竟最简单如果解决就不用下一个方法了. 1. (1)用U盘做一个ubuntu的镜像, 开机进入U ...
- 使用jdk获取网页
参考:https://www.zhihu.com/question/30626103 由于例子比较老了,现在的百度抓不到完整的页面了 import java.io.BufferedReader; im ...
- CCF 201512-1 数位之和 (水题)
问题描述 给定一个十进制整数n,输出n的各位数字之和. 输入格式 输入一个整数n. 输出格式 输出一个整数,表示答案. 样例输入 20151220 样例输出 13 样例说明 20151220的各位数字 ...
- VR视频原理
VR视频,这里指的是沉浸式全景视频,基本场景是观影者戴上显示头盔(如cardboard),在其中通过头部的转动可以看到全景视频的每个方向的图像.同时也能听到来自各个方向的声音,声音也会随着头部的转动而 ...
- lightoj1259 【素数预处理】
题意: 输出有多少对满足条件的(a,b) both a and b are prime; a+b=n a<=b; 思路: 一开始想的就是打表一个素数数组,然后还去二分..mdzz..直接判断一下 ...
- DataGridView Index -1 does not have a value 错误
遇到一个非常奇怪的问题, 一个DataGridView在装载数据后, 无论点击Column还是Cell都会报如下错误: 查bing之后发现StackOverFlow都指向DataSource的问题. ...
- PL/SQL基础知识
Oracle之PL/SQL学习笔记 自己在学习Oracle是做的笔记及实验代码记录,内容挺全的,也挺详细,发篇博文分享给需要的朋友,共有1w多字的学习笔记吧.是以前做的,一直在压箱底,今天拿出来整理了 ...
- 普通组件定义渲染和render渲染组件的区别(三)
普通方式定义组件和效果: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> ...
- JSP技术概念
- 基于php的AWS存储服务
近几天用到了aws的s3存储服务,公司内部的完全兼容aws并对其进行了封装,之前也用过,现在把经验总结一下. 既然要用,首先需要安装sdk,下边提供了几种安装方法 方法一:使用composer安装 1 ...