HDU 3669 Cross the Wall
题目大意
给定 $N$ 个矩形的宽和高, $(h_1, w_1), (h_2, w_2), \dots, (h_n w_n)$ . 现需要确定 $k$ ($k \le K$, $K$ 给定) 个矩形 $(H_i, W_i)$ , 使得 $\forall i \ (1\le i\le N), \exists j,\ s.t.\ H_j \ge h_i$ 且 $W_j \ge w_i$, 此时称这后 $k$ 个矩形覆盖前 $N$ 个矩形, 代价为 $\sum_{1\le i \le k} H_i W_i$ , 即 $k$ 个矩形的面积之和. 求覆盖这 $N$ 个矩形的最小代价.
Solution
DP方程
对 $N$ 个矩形按 (宽, 高) 双关键字从小到大排序. 按此顺序构造一个高严格递减的矩形队列, 只考虑这个队列里的矩形, 记队列里的剩下的矩形数目为 $n, \ (n \le N)$ .
$dp[i][j]$ : 用 $j$ 个矩形覆盖队列中前 $i$ 个矩形的最小代价.
$$
\begin{equation}
dp[i][j] = \min {dp[i'][j-1]+w_i \times h_{i'+1}} \quad (0\le i' <i) \label{dp_eq}
\end{equation}
$$
边界条件: $dp[0][0]=0$
斜率优化
固定 $j$ , 用斜率优化 $i$ 这一维的决策.
关于斜率优化的细致讨论见 this post.
写出斜率不等式:
$$
\begin{equation}
g(i_1, i_2) < f(i) \quad (i_1<i_2) \label{general_ineq}
\end{equation}
$$
其中
$$ g(i_1, i_2) = \dfrac{dp[i_2][j-1] - dp[i_1][j-1]}{h[i_1+1]-h[i_2+1]}$$
$$ f(i) = w[i]$$
维护一个相邻点斜率严格递增的点的队列, 由于 $f(i)$ 单调递增 , 在维护单调队列的基础上, 计算 $dp[i][j]$ 之前, 若队首两点 $i_1, i_2$ 满足 $g(i_1, i_2) \le f(i)$ , 就将队首元素出队, 重复该过程. 将队首元素代入 $\ref{dp_eq}$ 式右边计算 $dp[i][j]$ 的值.
Implementation
#include <bits/stdc++.h>
using namespace std;
const int N=5e4+5, K=105;
using ll=long long;
ll dp[N][K];
// dp[i][j]=min()
int n, k;
ll w[N], h[N];
bool cmp(int x, int y){
return w[x]<w[y] || w[x]==w[y] && h[x]<h[y]; // error-prone
}
int idx[N];
int q[N], t; // q[0]=0
void prep(){
for(int i=1; i<=n; i++)
idx[i]=i;
sort(idx+1, idx+n+1, cmp);
t=0;
// q[++tail]=idx[1];
for(int i=1; i<=n; i++){
while(t && h[q[t]]<=h[idx[i]])
--t;
q[++t]=idx[i];
}
}
// x < y: index of q
ll nu(int i, int x, int y){
return dp[y][i]-dp[x][i];
}
ll de(int x, int y){
return h[q[x+1]]-h[q[y+1]];
}
// the first dimension of dp[i][j] and q[i] are associated.
int que[N], head, tail;
int main(){
h[0]=1e6+5;
for(; cin>>n>>k; ){
for(int i=1; i<=n; i++)
scanf("%lld%lld", w+i, h+i);
prep();
for(int j=0; j<=k; j++)
dp[0][j]=0;
for(int i=1; i<=t; i++)
dp[i][0]=1e12+5; //error-prone
// p_i: (h[q[i+1]], dp[i])
for(int j=1; j<=k; j++){ // j: number of rectangles.
head=tail=0; // index of que
// 1. idx of q stored 2. 0-indexed
que[tail++]=0;
for(int i=1; i<=t; i++){ // i: index of q
while(tail-head>=2 &&
nu(j-1, que[head], que[head+1]) <= de(que[head], que[head+1])*w[q[i]])
++head;
dp[i][j]=dp[que[head]][j-1]+h[q[que[head]+1]]*w[q[i]];
// printf("(%d,%d):%lld\n", i, j, dp[i][j]);
while(tail-head>=2 &&
nu(j-1, que[tail-2], que[tail-1])*de(que[tail-1], i)
>=nu(j-1, que[tail-1], i)*de(que[tail-2], que[tail-1]))
--tail;
que[tail++]=i; //error-prone
}
}
ll res=LLONG_MAX;
for(int j=1; j<=k; j++)
res=min(res, dp[t][j]);
assert(res>0);
cout<<res<<endl;
}
return 0;
}
Pitfalls
如何将已经能被其他矩形覆盖的矩形剔除.
HDU 3669 Cross the Wall的更多相关文章
- hdu 3669 Cross the Wall(斜率优化DP)
题目连接:hdu 3669 Cross the Wall 题意: 现在有一面无限大的墙,现在有n个人,每个人都能看成一个矩形,宽是w,高是h,现在这n个人要通过这面墙,现在只能让你挖k个洞,每个洞不能 ...
- 动态规划DP的斜率优化 个人浅解 附HDU 3669 Cross the Wall
首先要感谢叉姐的指导Orz 这一类问题的DP方程都有如下形式 dp[i] = w(i) + max/min(a(i)*b(j) + c(j)) ( 0 <= j < i ) 其中,b, c ...
- HDU 3669 Cross the Wall(斜率DP+预处理)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3669 题目大意:有n(n<=50000)个矩形,每个矩形都有高和宽,你可以在墙上最多挖k个洞使得 ...
- HDU 3669 [Cross the Wall] DP斜率优化
问题分析 首先,如果一个人的\(w\)和\(h\)均小于另一个人,那么这个人显然可以被省略.如果我们将剩下的人按\(w[i]\)递增排序,那么\(h[i]\)就是递减. 之后我们考虑DP. 我们设\( ...
- hdu 3669(斜率优化DP)
Cross the Wall Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 327680/327680 K (Java/Others) ...
- hdu 1543 Paint the Wall
http://acm.hdu.edu.cn/showproblem.php?pid=1543 #include <cstdio> #include <cstring> #inc ...
- HDU 2124 Repair the Wall
http://acm.hdu.edu.cn/showproblem.php?pid=2124 Problem Description Long time ago , Kitty lived in a ...
- HDU 4391 Paint The Wall(分块+延迟标记)
Paint The Wall Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- hdu3669 Cross the Wall
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 327680/327680 K (Java/Others) Total Submissi ...
随机推荐
- zepto/jQuery、AngularJS、React、Nuclear的演化
写在前面 因为zepto.jQuery2.x.x和Nuclear都是为现代浏览器而出现,不兼容IE8,适合现代浏览器的web开发或者移动web/hybrid开发.每个框架类库被大量用户大规模使用都说明 ...
- iOS - 静态库的创建与使用
在日常项目开发中,不论是为了两个公司项目上的业务交流还是为了减少项目的编译时间,有的时候我们会把项目中的私密内容打包成静态库,或者是把项目中变动较少一部分打包成静态库以便提高编译效率,那么下面我们就来 ...
- Python 环境搭建,开发工具,基本语法
python环境 https://www.python.org/downloads/ 现在pthon有两个版本 一个是3.5系列的 , 一个是2.7系列的.建议用3.5版本的 开发工具 PyCharm ...
- Linux系统sar命令解析
安装 如果系统没有该命令请安装: apt-get install sysstat yum install sysstat 安装完毕: vi /etc/default/sysstat ENABLED=& ...
- js动态添加事件-事件委托
作者:白狼 出处:http://www.manks.top/javascript-dynamic-event.html 本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给 ...
- 配置mysql允许远程连接的方法
默认情况下,mysql只允许本地登录,如果要开启远程连接,则需要修改/etc/mysql/my.conf文件. 一.修改/etc/mysql/my.conf找到bind-address = 127.0 ...
- Linux LVM学习总结——扩展卷组VG
Linux服务器由于应用变更或需求的缘故,有可能出现分区空间不足的情况,此时往往需要进行扩容(要增加分区的空间),而采用LVM的好处就是可以在不需停机的情况下可以方便地调整各个分区大小.如下所示,分区 ...
- 使用批处理文件在FTP服务器 上传下载文件
1.从ftp服务器根目录文件夹下的文件到指定的文件夹下 格式:ftp -s:[配置文件] [ftp地址] 如:ftp -s:c:\vc\ftpconfig.txt 192.168.1.1 建立一个 ...
- 项目自动化建构工具gradle 入门2——log4j输出helloWorld
上一章节呢,有一个能跑的程序了.但是对做工程的人来说,用日志输出感觉比用System.out要有档次一点.比如使用log4j.直接上例子: 1进入D:\work\gradle\log目录 ,您电脑没 ...
- plain framework 1 一款主要用于网络(游戏)开发的C/C++开源框架 安装篇 updated
上次介绍了一下plain framework的基础相关资料,今天该框架正式开源发布.项目的地址托管于github上,我相信大多数朋友都应该知道.今天要介绍的是该框架的目录基本结构,以及分别在linux ...