hdu 3669 Cross the Wall(斜率优化DP)

题目连接:hdu 3669 Cross the Wall

题意:

现在有一面无限大的墙,现在有n个人,每个人都能看成一个矩形,宽是w,高是h,现在这n个人要通过这面墙,现在只能让你挖k个洞,每个洞不能重叠,每个洞需要消耗你挖的w*h,现在问你最小消耗多少。

题解:

设dp[i][j]为前j个人挖i个洞的最小消耗。

首先我们先将每个人按w排序,我们可以发现,排序后的h是递减的,因为如果不是递减的,可以把那个点消掉,因为w[k]<w[j]&&h[k]<h[j]的话,那么第k个人就可以直接过第j个人的洞。

然后我们可以预处理一下。

然后可以得

dp[i][j]=min{dp[i-1][k]+w[j]*h[k+1]}(k<j)

然后考虑斜率优化

设k>l,对于dp[i][j],第k个人到第j个人通过一个洞比第l个人到第j个人通过一个洞更优

有dp[i-1][k]+w[j]*h[k+1]<=dp[i-1][l]+w[j]*h[l+1];

整理得

dp[i-1][k]-dp[i-1][l]/h[l+1]-h[k+1]<=w[j];

然后单调队列优化一下就好。

 1 #include<bits/stdc++.h>
 2 #define F(i,a,b) for(int i=a;i<=b;++i)
 3 using namespace std;
 4 typedef long long ll;
 5
 6 const int N=5e4+7;
 7 int n,k,Q[N],ed;
 8 ll dp[101][N],ans,inf=1ll<<60;
 9 struct node
10 {
11     ll w,h;
12     bool operator < (const node &b)const{return w<b.w;}
13 }a[N],b[N];
14
15 ll getx(int k,int l){return -b[k+1].h+b[l+1].h;}
16 ll gety(int i,int k,int l){return dp[i][k]-dp[i][l];}
17 ll check(int i,int j,int k,int l){return gety(i,j,k)*getx(k,l)<=gety(i,k,l)*getx(j,k);}
18
19 int main()
20 {
21     while(~scanf("%d%d",&n,&k))
22     {
23         F(i,1,n)scanf("%lld%lld",&a[i].w,&a[i].h);
24         sort(a+1,a+1+n),ed=0;
25         F(i,1,n)
26         {
27             while(ed&&a[i].h>b[ed].h)ed--;
28             b[++ed]=a[i];
29         }
30         F(i,1,ed)dp[1][i]=b[i].w*b[1].h;
31         F(i,2,k)
32         {
33             int head=1,tail=0;
34             Q[++tail]=i-1;
35             F(j,i,ed)
36             {
37                 while(head<tail&&gety(i-1,Q[head+1],Q[head])<=b[j].w*getx(Q[head+1],Q[head]))head++;
38                 dp[i][j]=dp[i-1][Q[head]]+b[j].w*b[Q[head]+1].h;
39                 while(head<tail&&check(i-1,j,Q[tail],Q[tail-1]))tail--;
40                 Q[++tail]=j;
41             }
42         }
43         ans=inf;
44         F(i,1,k)if(ans>dp[i][ed])ans=dp[i][ed];
45         printf("%lld\n",ans);
46     }
47     return 0;
48 }

时间: 2024-10-05 06:31:18

hdu 3669 Cross the Wall(斜率优化DP)的相关文章

HDU 3507 Print Article(斜率优化DP)

题目链接 题意 : 一篇文章有n个单词,如果每行打印k个单词,那这行的花费是,问你怎么安排能够得到最小花费,输出最小花费. 思路 : 一开始想的简单了以为是背包,后来才知道是斜率优化DP,然后看了网上的资料,看得还挺懂的,不过我觉得如果以后真遇到斜率DP,要推起来肯定不简单..... 网上资料1 网上资料2 1 #include <iostream> 2 #include <stdio.h> 3 4 using namespace std; 5 6 int q[500005],dp

hdu 2993 MAX Average Problem (斜率优化dp入门)

MAX Average Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5855    Accepted Submission(s): 1456 Problem Description Consider a simple sequence which only contains positive integers as

Print Article hdu 3507 一道斜率优化DP 表示是基础题,但对我来说很难

Print Article Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 4990    Accepted Submission(s): 1509 Problem Description Zero has an old printer that doesn't work well sometimes. As it is antique

HDU 2829 Lawrence (斜率优化DP或四边形不等式优化DP)

题意:给定 n 个数,要你将其分成m + 1组,要求每组数必须是连续的而且要求得到的价值最小.一组数的价值定义为该组内任意两个数乘积之和,如果某组中仅有一个数,那么该组数的价值为0. 析:DP状态方程很容易想出来,dp[i][j] 表示前 j 个数分成 i 组.但是复杂度是三次方的,肯定会超时,就要对其进行优化. 有两种方式,一种是斜率对其进行优化,是一个很简单的斜率优化 dp[i][j] = min{dp[i-1][k] - w[k] + sum[k]*sum[k] - sum[k]*sum[

【转】斜率优化DP和四边形不等式优化DP整理

当dp的状态转移方程dp[i]的状态i需要从前面(0~i-1)个状态找出最优子决策做转移时 我们常常需要双重循环 (一重循环跑状态 i,一重循环跑 i 的所有子状态)这样的时间复杂度是O(N^2)而 斜率优化或者四边形不等式优化后的DP 可以将时间复杂度缩减到O(N) O(N^2)可以优化到O(N) ,O(N^3)可以优化到O(N^2),依次类推 斜率优化DP和四边形不等式优化DP主要的原理就是利用斜率或者四边形不等式等数学方法 在所有要判断的子状态中迅速做出判断,所以这里的优化其实是省去了枚举

HDOJ 3669 Cross the Wall

斜率优化DP... 按w递减,w相等h递增的顺序排序,扫一遍让w递减h递增 dp[now][i]=min( dp[pre][j]+W[j+1]*H[i])   k-1<=j<=i-1 维护一个下凸的曲线,斜率优化 Cross the Wall Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 327680/327680 K (Java/Others) Total Submission(s): 4340    Accepted Sub

HDU 3507 Print Article (斜率优化)

HDU 3507 Print Article (斜率优化) ACM 题目地址: HDU 3507 Print Article 题意: 给定一个长度为n的序列,和一个常数m,我们可以将序列分成随意段,每段的权值为sum(arr[i]) + C(x<=i<=y),求一种划分方法使得整个序列的权值最小 分析: from:亟隐's blog f[i]=min(f[k]+(sum(i)-sum(k))^2 )+m = f[k]+sum^2(i)+sum^2(k)-2*sum(i)*sum(k)+m. 也

【BZOJ1597】【Usaco2008 Mar】土地购买 斜率优化DP

题解:首先将块排个序,然后去掉被其它某块包含的块,然后斜率优化dp dp方程:f[i]=f[j]+a[i]*b[j+1]; 具体什么x啊y啊什么的在代码注释里面. --....纠结死了.开始各种WA,现在才发现: inline long long xmul(Point i,Point j,Point k){(i.y-j.y)*(j.x-k.x)-(j.y-k.y)*(i.x-j.x);} 上面的代码竟然能通过编译--,无力吐槽.以后一定要用终端+Wall命令编译文件了. warning一日不死,

斜率优化DP总结

前言: 也是好久没有写题解了,最近主要学习了单调栈单调队列以及斜率优化DP这几个知识点,对于较难的斜率优化DP,做个小小的总结吧. 正(che)文(dan): T1 hdu 3507 在一个风和日丽的早上,你打开了网页,点进了hdu,偶然间看到了这道题,不屑的以为这仅仅是一个很水的DP,2分钟给出DP方程式,很快的写完后发现n的范围居然是500000,这让已经推出来的 O(n2)复杂度的递推式情何以堪,所以就产生了一种高逼格的优化方式:斜率优化. 这道题的方程式是什么呢? dp[i]=min(d