题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3669

题目大意:有n(n<=50000)个矩形,每个矩形都有高和宽,你可以在墙上最多挖k个洞使得可以通过,问你最小花费(所有挖的洞的h*w之和)是多少。

解题思路:先将所有矩形按宽从大到小,高从大到小,如果一个矩形宽和高都小于等于前面的矩形则肯定会被前面的矩形覆盖(完全放在前面的矩形里),那么这个矩形就可以删掉,因为不影响结果。

最后再倒序,使得宽从小到大,高从大到小,则状态转移方程为:dp[i][j]=min{dp[k][j-1]+a[k+1].h*a[i].w}(j-1<=k<i)。这样写复杂度为O(m*n^2)。发现dp[i][j]存在单调性,可以用斜率DP优化,使得复杂度降为O(m*n)。注意:记得特判当挖洞数增加但总花费不减少时,直接跳出DP,否则很大可能会超时。

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 typedef long long LL;
 7 const int N=5e4+5;
 8 const int INF=0x3f3f3f3f;
 9
10 int head,tail;
11 LL dp[N][105],q[N];
12
13 struct node{
14     LL w,h;
15     bool operator <(const node &b)const{
16         return w==b.w?h>b.h:w>b.w;
17     }
18 }a[N],tmp[N];
19
20 LL getUP(int m,int k,int j){
21     return dp[k][j-1]-dp[m][j-1];
22 }
23
24 LL getDOWN(int m,int k){
25     return a[m+1].h-a[k+1].h;
26 }
27
28 LL getDP(int i,int j,int k){
29     return dp[k][j-1]+a[k+1].h*a[i].w;
30 }
31
32 int main(){
33     int n,m;
34     while(scanf("%d%d",&n,&m)!=EOF){
35         for(int i=1;i<=n;i++){
36             scanf("%lld %lld",&tmp[i].w,&tmp[i].h);
37         }
38         sort(tmp+1,tmp+1+n);
39         int cnt=1;
40         a[1].h=tmp[1].h,a[1].w=tmp[1].w;
41         //删除会被完全覆盖的矩形
42         for(int i=1;i<=n;i++){
43             if(a[cnt].h<tmp[i].h){
44                 cnt++;
45                 a[cnt].h=tmp[i].h;
46                 a[cnt].w=tmp[i].w;
47             }
48         }
49         reverse(a+1,a+1+cnt);
50         for(int i=1;i<=cnt;i++){
51             dp[i][1]=a[1].h*a[i].w;
52         }
53         LL ans=dp[cnt][1];
54
55         for(int j=2;j<=m;j++){
56             head=tail=0;
57             q[tail++]=j-1;
58             dp[cnt][j]=INF;
59             for(int i=j;i<=cnt;i++){
60                 while(head+1<tail&&getUP(q[head],q[head+1],j)<=a[i].w*getDOWN(q[head],q[head+1])){
61                     head++;
62                 }
63                 dp[i][j]=getDP(i,j,q[head]);
64                 while(head+1<tail&&getUP(q[tail-1],i,j)*getDOWN(q[tail-2],q[tail-1])<=getUP(q[tail-2],q[tail-1],j)*getDOWN(q[tail-1],i)){
65                     tail--;
66                 }
67                 q[tail++]=i;
68             }
69             //加一句特判(从超时变成146ms),当挖洞数增多,花费未降低的时候,说明再增加挖洞数也不会降低花费,直接结束DP
70             if(ans<=dp[cnt][j])
71                 break;
72             else
73                 ans=dp[cnt][j];
74         }
75         printf("%lld\n",ans);
76     }
77     return 0;
78 }

转载于:https://www.cnblogs.com/fu3638/p/7841614.html

HDU 3669 Cross the Wall(斜率DP+预处理)相关推荐

  1. HDU 3507 Print Article(斜率优化DP)

    题目链接 题意 : 一篇文章有n个单词,如果每行打印k个单词,那这行的花费是,问你怎么安排能够得到最小花费,输出最小花费. 思路 : 一开始想的简单了以为是背包,后来才知道是斜率优化DP,然后看了网上 ...

  2. hdu 3480 斜率dp

    思路:很普通的斜率dp #include<cstdio> #include<cstring> #include<iostream> #include<algo ...

  3. HDU 1520 Anniversary party(树形dp)

    HDU 1520 Anniversary party(树形dp) 树形dp第一题!!! 题意很清晰,思路也很明确.很容易找到根节点,即最大的boss,通过根节点向下dp. 状态转移方程: int to ...

  4. CodeForces - 1295C Obtain The String(dp预处理+贪心)

    题目链接:点击查看 题目大意:给出一个字符串 s 和一个字符串 t ,再给出一个字符串 z ,初始时字符串 z 为空串,现在需要利用规则构造字符串 z ,使得 z == t ,规则就是每次可以挑选字符 ...

  5. HDU 3001 三进制状压DP

    HDU 3001 三进制状压DP N个城市,M条道路,每条道路有其经过的代价,每一个城市最多能够到达两次,求走全然部城市最小代价,起点随意. 三进制状压.存储每一个状态下每一个城市经过的次数. 转移方 ...

  6. bzoj 3437: 小P的牧场(斜率DP)

    3437: 小P的牧场 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 1493  Solved: 830 [Submit][Status][Disc ...

  7. hdu 5155 Harry And Magic Box(DP)

    题目链接:hdu 5155 Harry And Magic Box dp[i][j]表示i∗j的矩阵方案数,dp[i][j]从dp[i−k][j−1]中转移,枚举前面j-1列中k行为空,那么这些行在第 ...

  8. hdu 3401 Trade(单调队列优化dp)

    hdu 3401 Trade(单调队列优化dp) 题意:lxhgww喜欢炒股票,他可以在第i天买入或者卖出若干张股票(一天只能买或者卖),两个交易日之间至少相隔w天,问他t天后最多能赚多少. 解题思路 ...

  9. HDU 4899 Hero meet devil (状压DP, DP预处理)

    题意:给你一个基因序列s(只有A,T,C,G四个字符,假设长度为n),问长度为m的基因序列s1中与给定的基因序列LCS是0,1......n的有多少个? 思路:最直接的方法是暴力枚举长度为m的串,然后 ...

最新文章

  1. Jpa-操作mongodb
  2. shell统计ip访问情况并分析访问日志
  3. pictrue获取图片的三种方式
  4. FFMPEG音视频同步-音频实时采集编码封装成MP4
  5. tcp拥塞控制_网络TCP的拥塞控制算法简介
  6. 辅助类BinaryTreeNode(二叉树节点)
  7. php实现服务器文件同步,PHPstorm配置同步服务器文件
  8. 深度学习中的专业英语词汇(by Youki)
  9. 初步搭建RocketMQ环境
  10. gitlab: [remote rejected] pre-receive hook declined
  11. java浮点数转整数_(题目2)自己实现浮点数转换为整数
  12. EVIEWS:ARCH类、GARCH、EGARCH,建模估计沪深300指数2019-2020年交易日的波动率,并对结果进行分析。
  13. 微信小程序中自定义select下拉选项框
  14. 办公室看VR黄片,微软「HoloLens之父」辞职!
  15. 照度计是什么测量原理
  16. c语言实数加法程序,蓝桥杯 算法提高 实数相加(c语言版附注释)
  17. 【登录及鉴权】-盘点那些主流的开源登录及权限认证框架 (上)
  18. PSR开关电源设计的得与失
  19. 秘密潜入1-普通枪械射速修改-Python源码
  20. 商业周刊:MySpace兴衰沉浮启示录(转)

热门文章

  1. js中变量名提升和函数名提升
  2. Perlin Noise
  3. mysql自动安装脚本
  4. 越知道自己要什么,越知道自己是什么
  5. SplitContainer.SplitterDistance属性值设置应注意的与FixedPanel有关
  6. python创建文件的编码格式
  7. linux c 获取文件数量
  8. gcc 编译多个源文件-转
  9. L1-021. 重要的话说三遍-PAT团体程序设计天梯赛GPLT
  10. oracle数据设置为ull,Oracle _11g_使用手册_自备