HDU - 5513 Efficient Tree(轮廓线DP)
前言
- 最近学了基于连通性的状压DP,也就是插头DP,写了几道题,发现这DP实质上就是状压+分类讨论,轮廓线什么的也特别的神奇。下面这题把我WA到死…
HDU-5531 Efficient Tree
给出一个n∗mn*mn∗m的网格图,以及相邻四联通格子之间的边权。
对于命题xxx,如果xxx成立,那么 [x]=1[x]=1[x]=1,否则 [x]=0[x]=0[x]=0
对于一颗生成树,每个点的贡献为 1+[有一条连向上的边]+[有一条连向左的边]1+[有一条连向上的边]+[有一条连向左的边]1+[有一条连向上的边]+[有一条连向左的边]。这棵树的贡献为所有点的贡献之积。要求:- 最小生成树的边权和
- 所有最小生成树的贡献之和。
n<=800,m<=7n<=800, m<=7n<=800,m<=7
由于mmm最大只有777,考虑轮廓线DP:
- f(i,j,S)f(i,j,S)f(i,j,S) 表示当前在 (i,j)(i,j)(i,j)这个点,轮廓线上方的格子联通情况为SSS的边权之和
- g(i,j,S)g(i,j,S)g(i,j,S) 表示当前在 (i,j)(i,j)(i,j)这个点,轮廓线上方的格子联通情况为SSS的贡献之和

- 黄色格子就是当前考虑的点,蓝色部分就是上一次状压的 mmm 个格子
- 此处的SSS是用最小表示法状压的,状态是长度为 mmm 的 888 进制数,每个位置上的值表示每一个蓝色格子在哪一个联通块里
- 这里的状压与普通插头DP有点不同,普通插头DP的状态长度是m+1m+1m+1,因为多算上了中间那一条竖着的轮廓线,而这里并不用。
转移比较简单,只要注意两点:
- 如果当前格子上面的格子在单独一个联通块,那么这条向上的边必须选,否则就无法形成一棵联通的树。
- 如果上面的格子和左边的格子在同一个联通块就不能合并,否则构成了一个环。
AC代码
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 805, MAXM = 10;
const int HASH = 10007, NUM = 1000005;
const int mod = 1e9+7, inf = 0x3f3f3f3f;
struct node {
int w, sum;
node(int _w=0, int _sum=0):w(_w), sum(_sum){}
inline node operator +(const node &t)const {
if(w < t.w) return *this;
if(w > t.w) return t;
return node(w, (sum+t.sum)%mod);
}
inline node operator +(const int &t)const {
return node(w+t, sum);
}
inline node operator *(const int &t)const {
return node(w, 1ll*sum*t%mod);
}
};
int n, m;
int L[MAXN][MAXM], U[MAXN][MAXM];
struct HashMap {
int val[NUM], adj[HASH], pre[NUM], tot;
node f[NUM];
inline void init() {
memset(adj, -1, sizeof adj); tot = 0;
}
inline void insert(const int &x, const node &tmp) {
int u = x % HASH;
for(int i = adj[u]; ~i; i = pre[i])
if(val[i] == x) {
f[i] = f[i] + tmp; return;
}
val[++tot] = x; pre[tot] = adj[u]; adj[u] = tot; f[tot] = tmp;
}
}h[2];
int msk[MAXM], id[MAXM];
inline void decode(int x) {
for(int i = m; i; --i, x>>=3) msk[i] = x&7;
}
inline int encode(const int &m) {
int res = 0, cur = 0;
memset(id, -1, sizeof id);
id[0] = 0;
for(int i = 1; i <= m; ++i) {
if(id[msk[i]] == -1) id[msk[i]] = ++cur;
res = (res<<3)|id[msk[i]];
//注意这里不能 msk[i]=id[msk[i]], 否则改变了 msk[i]的值, dp函数中的x,y值就不对了
}
return res;
}
inline void dp(const int &i, const int &j, const int &now) {
for(int k = 1; k <= h[now^1].tot; ++k) {
decode(h[now^1].val[k]);
int x = msk[j-1], y = msk[j];
bool one = 1;
for(int l = 0; l <= m; ++l) //看是否是独立的联通块
if(l != j && msk[l] == y) { one = 0; break; }
if(!one) { //自成联通块
msk[j] = 8; //赋值为不可能出现的8
h[now].insert(encode(m), h[now^1].f[k]);
msk[j] = y;
}
if(i > 1)
h[now].insert(encode(m), (h[now^1].f[k] + U[i][j])*2);//只连左边
if(j > 1 && !one) {
msk[j] = x;
h[now].insert(encode(m), (h[now^1].f[k] + L[i][j])*2);//只连上边
msk[j] = y;
}
if(i > 1 && j > 1 && x != y) { //两边都连
for(int l = 0; l <= m; ++l) if(msk[l] == x) msk[l] = y;
h[now].insert(encode(m), (h[now^1].f[k] + L[i][j] + U[i][j])*3);
}
}
}
int main () {
int T;
scanf("%d", &T);
for(int kase = 1; kase <= T; ++kase) {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i)
for(int j = 2; j <= m; ++j)
scanf("%d", &L[i][j]);
for(int i = 2; i <= n; ++i)
for(int j = 1; j <= m; ++j)
scanf("%d", &U[i][j]);
int now = 0; h[now].init(); h[now].insert(0, node(0, 1));
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j) {
now ^= 1; h[now].init();
dp(i, j, now);
}
node ans = node(inf, 0);
for(int i = 1; i <= h[now].tot; ++i) {
bool flag = 1;
decode(h[now].val[i]);
for(int j = 1; j < m; ++j)
if(msk[j] != msk[j+1]) { flag = 0; break; }
if(flag) ans = ans + h[now].f[i];
}
printf("Case #%d: %d %d\n", kase, ans.w, ans.sum);
}
}
PS:PS:PS:
我之所以WA就是因为encodeencodeencode函数里改变了mskmskmsk的值,出来后dpdpdp函数里的x,yx,yx,y就不对了,WA到自闭…
还有我的代码只用了msk[1...m]msk[1...m]msk[1...m],第000位没用
HDU - 5513 Efficient Tree(轮廓线DP)的更多相关文章
- HDU 5513 Efficient Tree
HDU 5513 Efficient Tree 题意 给一个\(N \times M(N \le 800, M \le 7)\)矩形. 已知每个点\((i-1, j)\)和\((i,j-1)\)连边的 ...
- hdu 5534 Partial Tree 背包DP
Partial Tree Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid= ...
- HDU - 4804 Campus Design 轮廓线dp
题意:一个nm的矩阵被12的骨牌和11的骨牌完全覆盖,11的骨牌只能放c-d次,矩阵中有障碍物 题解:dp[i][j][k]表示到了第i行,第j个状态,放过k个11的骨牌,当前位有障碍物时只有一种转移 ...
- HDU 1565 方格取数(1) 轮廓线dp
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1565 方格取数(1) Time Limit: 10000/5000 MS (Java/Others) ...
- HDU 4802 && HDU 4803 贪心,高精 && HDU 4804 轮廓线dp && HDU 4805 计算几何 && HDU 4811 (13南京区域赛现场赛 题目重演A,B,C,D,J)
A.GPA(HDU4802): 给你一些字符串对应的权重,求加权平均,如果是N,P不计入统计 GPA Time Limit: 2000/1000 MS (Java/Others) Memory ...
- HDU - 4804 Campus Design(状压+轮廓线dp)
Campus Design Nanjing University of Science and Technology is celebrating its 60th anniversary. In o ...
- 2013 ACM-ICPC亚洲区域赛南京站C题 题解 轮廓线DP
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4804 题目大意 给你一个 \(n \times m\) 的矩形区域.你需要用 \(1 \times 1 ...
- 轮廓线DP POJ3254 && BZOJ 1087
补了一发轮廓线DP,发现完全没有必要从右往左设置状态,自然一点: 5 6 7 8 9 1 2 3 4 如此设置轮廓线标号,转移的时候直接把当前j位改成0或者1就行了.注意多记录些信息对简化代码是很有帮 ...
- HDU 1003 Max Sum --- 经典DP
HDU 1003 相关链接 HDU 1231题解 题目大意:给定序列个数n及n个数,求该序列的最大连续子序列的和,要求输出最大连续子序列的和以及子序列的首位位置 解题思路:经典DP,可以定义 ...
随机推荐
- Python爬虫:现学现用xpath爬取豆瓣音乐
爬虫的抓取方式有好几种,正则表达式,Lxml(xpath)与BeautifulSoup,我在网上查了一下资料,了解到三者之间的使用难度与性能 三种爬虫方式的对比. 这样一比较我我选择了Lxml(xpa ...
- 文件包含lfi
CG-CTF web(文件包含漏洞) 参考链接:https://blog.csdn.net/qq_34072526/article/details/89431431 php://filter 的使用: ...
- lsyncd实时同步工具
简介 Lysncd 实际上是lua语言封装了 inotify 和 rsync 工具,采用了 Linux 内核(2.6.13 及以后)里的 inotify 触发机制,然后通过rsync去差异同步,达到实 ...
- Locust性能测试-环境准备与基本使用 转自:悠悠
前言 提到性能测试,大部分小伙伴想到的就是LR和jmeter这种工具,小编一直不太喜欢写这种工具类的东西,我的原则是能用代码解决的问题,尽量不去用工具. python里面也有一个性能测试框架Locus ...
- 对一次 redis 未授权写入攻击的分析以及学习
前段时间自己使用 redis 开发的时候,搞了一个 docker ,然后直接开放连接没有密码,其实一开始我就知道会被黑产扫到然后给我种马,但是把因为也是测试服务,其实也没怎么上心,于是就放任自由了,结 ...
- 《JAVA高并发编程详解》-Thread start方法的源码
Thread start方法的源码:
- C# vb .net实现焦距柔化特效滤镜
在.net中,如何简单快捷地实现Photoshop滤镜组中的焦距柔化效果呢?答案是调用SharpImage!专业图像特效滤镜和合成类库.下面开始演示关键代码,您也可以在文末下载全部源码: 设置授权 第 ...
- python 代码中log表示含义
log表示以e为底数的对数函数符号.其验证代码如下: a=np.log(np.e )print(a)print(np.e)
- Python进阶----表与表之间的关系(一对一,一对多,多对多),增删改查操作
Python进阶----表与表之间的关系(一对一,一对多,多对多),增删改查操作,单表查询,多表查询 一丶表与表之间的关系 背景: 由于如果只使用一张表存储所有的数据,就会操作数 ...
- Python进阶(十三)----面向对象
Python进阶(十三)----面向对象 一丶面向过程编程vs函数式编程vs面向对象编程 面向过程: 简而言之,step by step 一步一步完成功能,就是分析出解决问题所需要的步骤,然后用函 ...