HDU_3669 斜率优化DP
来源:互联网 发布:怎么查4g网络覆盖 编辑:程序博客网 时间:2024/05/16 07:19
虽然是一道水题,TLE+WA了一天,WA的原因是因为自己粗心了,DP的范围明明超过了int,强行用int来写。(不过很快就改过来了,然后T了一天)至于T的原因,只能说自己太蠢,HDU给了我一种错觉,总觉得C++跑得要比G++快,然后加了10发C++全T了,最后抱着试试看的心情交了一发G++,AC了。。。只跑了452ms。。。然后把第一次敲的代码放上去,也妥妥地AC了。。。唉。。。
首先,这道题的转移方程比较好写:dp[i][m] = min{dp[j][m-1]+w[i]*h[j+1]}。在这之前,我们需要把每一个矩形进行排序,按照w排(h排也行),然后w相同的按照h排,顺序都是从大到小,目的就是去掉w[j]<=w[i] && h[j]<=h[i]的矩形,因为这样的矩形没有任何意义。
然后对于: i > j > K:
G(j,k) = (dp[j][m-1] - dp[k][m-1])/(h[k+1]-h[j+1]) < w[i] :j点比k点优,k点可以删除,因为w[i]单调的,所以后面的点,j点总是比k点优。
G(j,k) >= G(i,j):则j点可以删除。
这道题由一维变成了二维,其实,只需要用队列维护dp[i][pre]的凸包就好了。
因为对内存要求不是很高,所以直接搞就好了,如果题目对内存有要求,那么最好换成滚动数组来写。
下面附上AC代码:
然后对于: i > j > K:
G(j,k) = (dp[j][m-1] - dp[k][m-1])/(h[k+1]-h[j+1]) < w[i] :j点比k点优,k点可以删除,因为w[i]单调的,所以后面的点,j点总是比k点优。
G(j,k) >= G(i,j):则j点可以删除。
这道题由一维变成了二维,其实,只需要用队列维护dp[i][pre]的凸包就好了。
因为对内存要求不是很高,所以直接搞就好了,如果题目对内存有要求,那么最好换成滚动数组来写。
下面附上AC代码:
#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <cmath>#include <cstdlib>#include <map>#include <queue>#include <stack>#define ll long long#define FOR(i,x,y) for(int i = x;i < y;i ++)#define N 55555#define K 111using namespace std;typedef pair<ll,ll> P;ll dp[N][K];int n,k,cnt;ll w[N],h[N],w_tem[N],h_tem[N],q[N],tail,head;P ret[N];ll G_UP(int i,int j,int k){ return (dp[i][k]-dp[j][k]);}ll G_DOWN(int i,int j){ return (h[j+1]-h[i+1]);}ll G_DP(int i,int j,int k){ return dp[j][k]+w[i]*h[j+1];}bool cmp(P a,P b){ if(a.first < b.first) return true; if(a.first == b.first && a.second < b.second) return true; return false;}void init(){ cnt = 0; w_tem[cnt] = ret[n-1].first; h_tem[cnt++] = ret[n-1].second; for(int i = n-2;i >= 0;i--){ if(ret[i].second <= h_tem[cnt-1]) continue; w_tem[cnt] = ret[i].first; h_tem[cnt++] = ret[i].second; } FOR(i,0,cnt){ w[i] = w_tem[cnt-1-i]; h[i] = h_tem[cnt-1-i]; } FOR(i,0,cnt){ dp[i][1] = w[i] * h[0]; }}void solve(){ if(k > cnt) k = cnt; FOR(m,2,k+1){ head = tail = 0; q[tail++] = m-2; for(int i = m-1;i < cnt;i ++){ while(head+1 < tail && (G_UP(q[head+1],q[head],m-1)) <= (G_DOWN(q[head+1],q[head])*w[i])) head++; dp[i][m] = G_DP(i,q[head],m-1); while(head+1 < tail && (G_UP(q[tail-1],q[tail-2],m-1)*G_DOWN(i,q[tail-1]) >= G_DOWN(q[tail-1],q[tail-2])*G_UP(i,q[tail-1],m-1))) tail--; q[tail++] = i; } }}int main(){ //freopen("test.in","r",stdin); while(~scanf("%d%d",&n,&k)){ ll x,y; FOR(i,0,n){ scanf("%I64d%I64d",&x,&y); ret[i] = make_pair(x,y); } sort(ret,ret+n,cmp); init(); solve(); ll ans = dp[cnt-1][1]; FOR(i,2,k+1){ ans = min(ans,dp[cnt-1][i]); } printf("%I64d\n",ans); } return 0;}
附上滚动数组版:
#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <cmath>#include <cstdlib>#include <map>#include <queue>#include <stack>#define N 50010#define K 105using namespace std;typedef long long ll;struct Node{ ll x,y;}ret[N];ll dp[N][2];int n,k,cnt;ll w[N],h[N],w_tem[N],h_tem[N],q[N],tail,head;ll ans;ll G_UP(int i,int j,int k){ return (dp[i][k]-dp[j][k]);}ll G_DOWN(int i,int j){ return (h[j+1]-h[i+1]);}ll G_DP(int i,int j,int k){ return dp[j][k]+w[i]*h[j+1];}bool cmp(Node a,Node b){ if(a.x < b.x) return true; if(a.x == b.x && a.y < b.y) return true; return false;}void init(){ cnt = 0; w_tem[cnt] = ret[n-1].x; h_tem[cnt++] = ret[n-1].y; for(int i = n-2;i >= 0;i--){ if(ret[i].y <= h_tem[cnt-1]) continue; w_tem[cnt] = ret[i].x; h_tem[cnt++] = ret[i].y; } for(int i = 0;i < cnt;i ++){ w[i] = w_tem[cnt-1-i]; h[i] = h_tem[cnt-1-i]; } for(int i = 0;i < cnt;i ++){ dp[i][0] = w[i] * h[0]; } ans = dp[cnt-1][0];}void solve(){ if(k >= cnt) k = cnt; int pre = 0,cur = 1; for(int m = 2;m <= k;m ++){ head = tail = 0; q[tail++] = m-2; for(int i = m-1;i < cnt;i ++){ while(head+1 < tail && (G_UP(q[head+1],q[head],pre)) < (G_DOWN(q[head+1],q[head])*w[i])) head++; dp[i][cur] = G_DP(i,q[head],pre); while(head+1 < tail && (G_UP(q[tail-1],q[tail-2],pre)*G_DOWN(i,q[tail-1]) >= G_DOWN(q[tail-1],q[tail-2])*G_UP(i,q[tail-1],pre))) tail--; q[tail++] = i; } ans = min(ans,dp[cnt-1][cur]); cur = 1-cur; pre = 1-pre; }}int main(){ //freopen("test.in","r",stdin); while(~scanf("%d%d",&n,&k)){ for(int i = 0;i < n;i ++){ scanf("%I64d%I64d",&ret[i].x,&ret[i].y); } sort(ret,ret+n,cmp); init(); solve(); printf("%I64d\n",ans); } return 0;}
0 0
- HDU_3669 斜率优化DP
- DP(斜率优化)
- 【斜率优化DP】Batch_Scheduling
- dp优化--斜率
- 斜率优化DP
- 斜率优化DP
- hdu3507斜率优化dp
- DP斜率优化总结
- hdu3480 斜率优化dp
- hdu3507 斜率优化dp
- 斜率优化DP
- 斜率优化DP 【pascal】
- 斜率优化DP
- dp 斜率优化
- 斜率优化 DP
- dp斜率优化
- DP斜率优化
- hdu4258 斜率优化dp
- <br/>与\n的区别
- 快速回收复用TCP的TIME_WAIT
- #19 Remove Nth Node From End of List
- 20150521-Allegro出图2-光绘文件
- ViewPager和Fragment的组合使用
- HDU_3669 斜率优化DP
- make 2>&1 | tee build.log
- iOS7的适配小问题, uiscrollview中view向下偏移64
- notification 详解
- apache poi导出excel
- 26>ASI的基本使用
- Illegal use of <when>-style tag without <choose> as its direct parent
- python中if __name__ == '__main__': 的解析
- 五、GDI图形基础