HDU 5513 Efficient Tree

题意

  • 给一个\(N \times M(N \le 800, M \le 7)\)矩形。
  • 已知每个点\((i-1, j)\)和\((i,j-1)\)连边的花费,求最小生成树的权和。
  • 对于每棵最小生成树\(T\),求\(\tau(T)=\prod{LRdeg_u}\)的,其中\(LRdeg_u\)表示左、上方连边的个数+1。

思路

  • 因为\(M\)很小,可以考虑轮廓线DP,记录前\(M\)个格子的连通信息。
  • 对于每个格子\((i, j)\)有4种转移:
  1. 不与\((i, j-1)\)和\((i - 1, j)\)连边:此时\((i-1, j)\)的连通块不能被当前格子给挡住。
  2. 和\((i,j - 1)\)和\((i-1,j)\)都有连边:那么两个格子的连通块不能一样,否则会成环。
  3. 和\((i, j-1)\)连边:直接染色即可。
  4. 和\((i-1,j)\)连边:同1,不能挡住\((i-1,j)\)的连通块。
  • 出现的几个问题:
  1. 之前写的都是简单回路和简单路径,所以每次转移只有其中一种,而做这道题应该每种都要考虑,并且每次转移前都要重新解码,否则信息会由于之前的转移发生改变。
  2. 需要再认真读几遍《基于连通性状态压缩的动态规划问题》这篇论文。
#include<cstdio>
#include<cstring>
#include<map>
#include<set>
#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;
#define pb push_back
#define sz(x) ((int)(x).size())
#define rep(i,l,r) for(int i=(l);i<(r);++i)
typedef long long ll;
typedef pair<int, int> pii;
const int N = 1e5 + 7;
const int INF = 2e9 + 7;
const int MOD = 1e9 + 7;
//--------head--------
void inc(int &x, int y) {
x += y;
if (x >= MOD)
x -= MOD;
}
int S, cod[20], col[20];
void decode(int a[], int n, int st) {
for (int i = n; i >= 0; --i, st >>= 3)
a[i] = st & 7;
}
int encode(int a[], int n) {
int id = 0, st = 0;
memset(col, -1, sizeof(col)), col[0] = 0;
for (int i = 0; i <= n; ++i) {
if (col[a[i]] == -1)
col[a[i]] = ++id;
a[i] = col[a[i]];
st = (st << 3) | a[i];
}
return st;
}
struct Hash {
const static int H = 1e4 + 7, N = 5e6 + 7;
int n, nxt[N], head[H];
int st[N], w[N], d[N];
void init() {
n = 0, memset(head, -1, sizeof(head));
}
void ins(int _st, int _w, int _d) {
int p = _st % H;
for (int i = head[p]; ~i; i = nxt[i])
if (st[i] == _st) {
if (_w < w[i]) {
w[i] = _w, d[i] = _d;
} else if (_w == w[i]) {
inc(d[i], _d);
}
return ;
}
st[n] = _st, w[n] = _w, d[n] = _d;
nxt[n] = head[p], head[p] = n++;
}
void out() {
for (int p = 0; p < H; ++p)
for (int i = head[p]; ~i; i = nxt[i]) {
decode(cod, S, st[i]);
rep(j, 0, S + 1)
printf("%d", cod[j]);
printf("(%d) %d %d\n", st[i], w[i], d[i]);
}
}
} hs[2];
int n, m, v[807][8], h[807][8];
void blank(int x, int y, int t) {
rep(i, 0, hs[t].n) {
decode(cod, S, hs[t].st[i]);
int U = cod[y], flag = 0;
if (x == 0)
flag = 1;
else if (U > 0) {
rep(j, 0, m)
if (j != y && cod[j] == U) {
flag = 1;
break;
}
}
if (x > 0 && U > 0) {
hs[t ^ 1].ins(hs[t].st[i], hs[t].w[i] + v[x][y],
2ll * hs[t].d[i] % MOD);
}
if (y > 0 && flag) {
decode(cod, S, hs[t].st[i]);
cod[y] = cod[y - 1];
hs[t ^ 1].ins(encode(cod, S), hs[t].w[i] + h[x][y],
2ll * hs[t].d[i] % MOD);
}
if (flag) {
decode(cod, S, hs[t].st[i]);
cod[y] = 14;
hs[t ^ 1].ins(encode(cod, S), hs[t].w[i], hs[t].d[i]);
}
if (x > 0 && y > 0 && cod[y - 1] != U) {
decode(cod, S, hs[t].st[i]);
int L = cod[y - 1];
rep(j, 0, m)
if (cod[j] == U)
cod[j] = L;
hs[t ^ 1].ins(encode(cod, S), hs[t].w[i] + v[x][y] + h[x][y],
3ll * hs[t].d[i] % MOD);
}
}
}
int main() {
int T;
scanf("%d", &T);
rep(cas, 0, T) {
scanf("%d%d", &n, &m), S = m - 1;
rep(i, 0, n)
rep(j, 1, m)
scanf("%d", &h[i][j]);
rep(i, 1, n)
rep(j, 0, m)
scanf("%d", &v[i][j]);
int t = 0;
hs[t].init();
hs[t].ins(0, 0, 1);
rep(i, 0, n)
rep(j, 0, m) {
t ^= 1;
hs[t].init();
blank(i, j, t ^ 1);
}
fill_n(cod, m, 1);
int st = encode(cod, S);
int mst = -1, deg = -1;
rep(i, 0, hs[t].n)
if (hs[t].st[i] == st)
mst = hs[t].w[i], deg = hs[t].d[i];
printf("Case #%d: %d %d\n", cas + 1, mst, deg);
}
return 0;
}

HDU 5513 Efficient Tree的更多相关文章

  1. HDU - 5513 Efficient Tree(轮廓线DP)

    前言 最近学了基于连通性的状压DP,也就是插头DP,写了几道题,发现这DP实质上就是状压+分类讨论,轮廓线什么的也特别的神奇.下面这题把我WA到死- HDU-5531 Efficient Tree 给 ...

  2. HDU 4925 Apple Tree(推理)

    HDU 4925 Apple Tree 题目链接 题意:给一个m*n矩阵种树,每一个位置能够选择种树或者施肥,假设种上去的位置就不能施肥,假设施肥则能让周围果树产量乘2.问最大收益 思路:推理得到肯定 ...

  3. HDU 4871 Shortest-path tree 最短路 + 树分治

    题意: 输入一个带权的无向连通图 定义以顶点\(u\)为根的最短路生成树为: 树上任何点\(v\)到\(u\)的距离都是原图最短的,如果有多条最短路,取字典序最小的那条. 然后询问生成树上恰好包含\( ...

  4. Hdu 5379 Mahjong tree (dfs + 组合数)

    题目链接: Hdu 5379 Mahjong tree 题目描述: 给出一个有n个节点的树,以节点1为根节点.问在满足兄弟节点连续 以及 子树包含节点连续 的条件下,有多少种编号方案给树上的n个点编号 ...

  5. HDU 6035 - Colorful Tree | 2017 Multi-University Training Contest 1

    /* HDU 6035 - Colorful Tree [ DFS,分块 ] 题意: n个节点的树,每个节点有一种颜色(1~n),一条路径的权值是这条路上不同的颜色的数量,问所有路径(n*(n-1)/ ...

  6. HDU 3333 - Turing Tree (树状数组+离线处理+哈希+贪心)

    题意:给一个数组,每次查询输出区间内不重复数字的和. 这是3xian教主的题. 用前缀和的思想可以轻易求得区间的和,但是对于重复数字这点很难处理.在线很难下手,考虑离线处理. 将所有查询区间从右端点由 ...

  7. HDU 5573 Binary Tree 构造

    Binary Tree 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5573 Description The Old Frog King lives ...

  8. hdu 4786 Fibonacci Tree (2013ACMICPC 成都站 F)

    http://acm.hdu.edu.cn/showproblem.php?pid=4786 Fibonacci Tree Time Limit: 4000/2000 MS (Java/Others) ...

  9. hdu 5534 Partial Tree 背包DP

    Partial Tree Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid= ...

随机推荐

  1. JSON初步

    1.什么是JSON (1)JSON(Java Script Object Notation)是一种轻量级的数据交换语言, 以文本字符串为基础,且易于让人阅读 XML就是一个重量级的数据交换语言 (2) ...

  2. android asyncTask 详解

    只看http://www.cnblogs.com/xiaoluo501395377/p/3430542.html  足以

  3. 100个iOS开发/设计面试题汇总

    常见问题 你昨天/这周学习了什么? 你为什么热衷于软件开发? 你对哪一种控制系统比较熟悉? 是否参与过GitHub项目? 是否参与过GitHub或其他同类型网站的iOS开源项目? 请描述一下你的iOS ...

  4. key 4v4

    #include "key4v4.h" #include "stm32f10x.h" #include "delay.h" /* PA4-L ...

  5. Struts2 的ModelDriven理解

    以UserAction为例,当UserAction实现了ModelDriven接口之后,与该接口相关的默认配置的拦截器会在拦截请求之后判断该请求是将要被UserAction处理而且UserAction ...

  6. Block编程值得注意的那些事儿

    [深入浅出Cocoa]Block编程值得注意的那些事儿   [深入浅出Cocoa]Block编程值得注意的那些事儿 罗朝辉 (http://www.cnblogs.com/kesalin/) 本文遵循 ...

  7. win7下利用笔记本无线网卡创建AP 组建无线局域网(可以连魔兽,TCP、UDP也没问题)

    转自:http://blog.163.com/fghok_018/blog/static/122599670201072773924530/ 近一个月,宿舍的好多同学都买了笔记本电脑,当然,我也买了, ...

  8. ios中摄像头/相册获取图片,压缩图片,上传服务器方法总结

    相册 iphone的相册包含摄像头胶卷+用户计算机同步的部分照片.用户可以通过UIImagePickerController类提供的交互对话框来从相册中选择图像.但是,注意:相册中的图片机器路径无法直 ...

  9. BZOJ 2296 随机种子

    RT. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> ...

  10. Python OpenCV——Image

    最近看MATLAB有点看不下去...就忍不住回到python的怀抱.研究下OpenCV,就当放松啦,对视觉还是很感兴趣的. 这里和之后代码大部分是来自这里的文档. 首先是对图片的处理. ''' imp ...