【算法】DP+斜率优化

【题意】n(n≤50000)块土地,长ai宽bi,可分组购买,每组代价为max(ai)*max(bi),求最小代价。

【题解】

斜率优化:http://www.cnblogs.com/ka200812/archive/2012/08/03/2621345.html

因为对于土地x和y,若满足a[x]<=a[y]&&b[x]<=b[y],则x土地可无条件包含在y土地中,所以x土地可以忽略。

于是对长度从小到大排序,第二关键字对宽度从小到大排序,处理掉可被包含块。

则有a严格升序,b严格降序

然后就是常规DP。

状态转移方程:f[i]=min(f[j]+a[i]*b[j+1])(j:0~i-1)

O(n^2)的效率显然不足,考虑斜率优化。

下面只从代数上理解斜率优化。

阶段i时对于决策j和k (j<k),当k更优时满足

f[j]+a[i]*b[j+1]>f[k]+a[i]*b[k+1]

即(f[j]-f[k])/(b[k+1]-b[j+1])<a[i]

令d(j,k)=(f[j]-f[k])/(b[k+1]-b[j+1]),

当d(j,k)<a[i]时,k决策优于j决策,决策的位置就会往后移;当d(j,k)>a[i]时,j决策优于k决策,决策的位置就会往前移。

我们认为d(j,k)越小越容易把决策往后送,定义为更优,也就是斜率越小越优。

于是维护一个决策队列,队列严格要求两两之间的d从最优到最劣,因为a[i]递增,当有一个新的a[i]时,前面的d(j,k)小的把决策后推,直到遇到大的就停下来,确定了最优决策。

为什么要维护决策队列的d从最优到最劣?设决策j,k,l(j<k<l),因为若有d(j,k)>d(k,l),当a[i]<d(k,l)时,j>k>l,当d(k,l)<a[i]<d(j,k)时,j>k&&l>k,当a[i]>d(j,k)时,l>k>j。可以发现,无论何时决策k都不会被选择,故应当删去。

斜率不是真实的,它只是比较优劣的工具,决策的优劣只与a[i]有关,而斜率只是比较两决策优劣与a[i]的关系。

但是我们为什么要定义斜率的优劣?因为右项a[i]单调递增。

所以删去k后,j和l之间会出现新的斜率,当a[i]和这个斜率发生大小变化时,j或l的选择将会改变。

整个过程可以想象成维护下凸包,不再赘述。

斜率优化题目的通法:

1.分离:列出决策优劣比较式(i阶段,j<k且k更优时),分离i和j k,当i有关变量呈现单调性质时可以进行斜率优化,根据不等关系定义斜率的优劣,维护从最优到最劣的决策队列。

2.决策:选取队头两个决策d(head,head+1),若d满足优劣式说明k更优,删除队头j,继续比较;若d不满足优劣式说明j更优,则j为当前最优决策。

3.入队:选取队尾两个决策d1(tail-1,tail)和当先决策与队尾决策的d2(tail,i),若d2优于d1则删除队尾,继续比较,直到d2劣于d1就把i入队。

【注意】long long=1ll*int*int,记得类型转换……。

  1. #include<cstdio>
  2. #include<algorithm>
  3. using namespace std;
  4. const int maxn=;
  5. long long f[maxn];
  6. int q[maxn],n;
  7. struct cyc{int x,y;}a[maxn],b[maxn];
  8. bool cmp(cyc a,cyc b)
  9. {return a.x<b.x||(a.x==b.x&&a.y<b.y);}
  10. double d(int j,int k)
  11. {return (f[j]-f[k])/(a[k+].y-a[j+].y);}//1.0*
  12. int main()
  13. {
  14. scanf("%d",&n);
  15. for(int i=;i<=n;i++)scanf("%d%d",&b[i].x,&b[i].y);
  16. sort(b+,b+n+,cmp);
  17. int m=;a[]=b[];
  18. for(int i=;i<=n;i++)
  19. {
  20. while(b[i].y>=a[m].y&&m>)m--;
  21. a[++m]=b[i];
  22. }
  23. n=m;
  24. // for(int i=1;i<=n;i++)printf("%d %d\n",a[i].x,a[i].y);
  25. // f[0]=a[0].x=a[0].y=0;
  26. int head=,tail=;q[]=;
  27. for(int i=;i<=n;i++)
  28. {
  29. while(tail-head>=&&d(q[head],q[head+])<a[i].x)head++;
  30. f[i]=f[q[head]]+1ll*a[i].x*a[q[head]+].y;
  31. // printf("f[%d]=%lld\n",i,f[i]);
  32. while(tail-head>=&&d(q[tail-],q[tail-])>d(q[tail-],i))tail--;//ÕâÑùÉèÖöÓÁУ¬tail´¦Ã»ÓÐÊý×Ö¡­¡­
  33. q[tail++]=i;
  34. }
  35. printf("%lld",f[n]);
  36. return ;
  37. }

【BZOJ】1597 [Usaco2008 Mar]土地购买的更多相关文章

  1. BZOJ 1597: [Usaco2008 Mar]土地购买 [斜率优化DP]

    1597: [Usaco2008 Mar]土地购买 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4026  Solved: 1473[Submit] ...

  2. BZOJ 1597: [Usaco2008 Mar]土地购买( dp + 斜率优化 )

    既然每块都要买, 那么一块土地被另一块包含就可以不考虑. 先按长排序, 去掉不考虑的土地, 剩下的土地长x递增, 宽y递减 dp(v) = min{ dp(p)+xv*yp+1 } 假设dp(v)由i ...

  3. BZOJ 1597: [Usaco2008 Mar]土地购买【斜率优化+凸包维护】

    1597: [Usaco2008 Mar]土地购买 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4989  Solved: 1847[Submit] ...

  4. BZOJ 1597: [Usaco2008 Mar]土地购买 斜率优化

    1597: [Usaco2008 Mar]土地购买 Time Limit: 10 Sec  Memory Limit: 162 MB Description 农夫John准备扩大他的农场,他正在考虑N ...

  5. 斜率优化专题1——bzoj 1597 [Usaco2008 Mar] 土地购买 题解

    转载请注明:http://blog.csdn.net/jiangshibiao/article/details/24387147 [原题] 1597: [Usaco2008 Mar]土地购买 Time ...

  6. BZOJ 1597 [Usaco2008 Mar]土地购买:斜率优化dp

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1597 题意: 有n块矩形土地,长为a[i],宽为b[i]. FJ想要将这n块土地全部买下来 ...

  7. bzoj 1597: [Usaco2008 Mar]土地购买

    Description 农 夫John准备扩大他的农场,他正在考虑N (1 <= N <= 50,000) 块长方形的土地. 每块土地的长宽满足(1 <= 宽 <= 1,000 ...

  8. bzoj 1597 [Usaco2008 Mar]土地购买——斜率优化dp

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1597 又一道斜率优化dp.负数让我混乱.不过仔细想想还是好的. 还可以方便地把那个负号放到x ...

  9. bzoj 1597: [Usaco2008 Mar]土地购买【斜率优化】

    按xy降序排序,把能被完全包含的去掉 然后就得到了x升序y降序的一个数组 然后方程就显然了:f[i]=min(f[j]+y[j+1]x[i]) 斜率优化转移 说起来我还不会斜率优化呢是不是该学一下了 ...

  10. BZOJ 1597: [Usaco2008 Mar]土地购买 动态规划 + 斜率优化

    Code: #include<bits/stdc++.h> #define maxn 1000000 #define ll long long #define x(i) (b[i+1]) ...

随机推荐

  1. Jquery获取属性值

    jq获取某个标签内的属性值:$("#TeamPerformanceYearUl li:eq(0)").attr('data') jq获取li或者td第一个属性(索引值从零开始)$( ...

  2. JNDI和JDBC

    没有JNDI的做法:程序员开发时,知道要开发访问MySQL数据库的应用,于是将一个对 MySQL JDBC 驱动程序类的引用进行了编码,并通过使用适当的 JDBC URL 连接到数据库.就像以下代码这 ...

  3. ngx_http_rewrite_module(重定向)

    1:指定rewrite规则 rewrite regex replacement [flag];   什么是rewrite规则:If the specified regular expression m ...

  4. jQuery之属性

    1. 操作任意属性 attr() 操作非布尔值的 removeAttr() prop() 操作布尔值的2. 操作class属性 addClass() 添加class属性 removeClass() 移 ...

  5. 多tab点击切换

    现在来一个小练习,就是用js实现多tab之间的切换: <body> <ul id="tab"> <li id="tab1"> ...

  6. session,cookie

    简单: cookie可以由客户端,服务端产生,保存在客户端,客户端可以更改cookie中的内容 session只能在服务端产生,保存在服务端,会产生一个session_id,一个域下,只有一个id,这 ...

  7. Centos上Apache重启,mysql重启,nginx重启方法

    转载:http://www.3lian.com/edu/2012/04-01/24278.html Centos上Apache重启,mysql重启, nginx 重启方法 1.重启 apache se ...

  8. 如果使用引用方式引用了js后 则不能再本地写js 因为写了后不会有效果

    如果使用引用方式引用了js后 则不能再本地写js 因为写了后不会有效果

  9. BZOJ 1965 洗牌(扩展欧几里得)

    容易发现,对于牌堆里第x张牌,在一次洗牌后会变成2*x%(n+1)的位置. 于是问题就变成了求x*2^m%(n+1)=L,x在[1,n]范围内的解. 显然可以用扩展欧几里得求出. # include ...

  10. Qt消息机制和事件

    Qt消息机制和事件 1 事件 事件(event)是由系统或者 Qt 本身在不同的时刻发出的.当用户按下鼠标.敲下键盘,或者是窗口需要重新绘制的时候,都会发出一个相应的事件.一些事件在对用户操作做出响应 ...