【Usaco2008 Mar】土地购买
【题目描述】
农夫John准备扩大他的农场,他正在考虑N (1 <= N <= 50,000) 块长方形的土地. 每块土地的长宽满足(1 <= 宽 <= 1,000,000; 1 <= 长 <= 1,000,000).
每块土地的价格是它的面积,但FJ可以同时购买多快土地. 这些土地的价格是它们最大的长乘以它们最大的宽, 但是土地的长宽不能交换. 如果FJ买一块3x5的地和一块5x3的地,则他需要付5x5=25.
FJ希望买下所有的土地,但是他发现分组来买这些土地可以节省经费. 他需要你帮助他找到最小的经费.
【输入格式】
- 第1行: 一个数: N
- 第2..N+1行: 第i+1行包含两个数,分别为第i块土地的长和宽
【输出格式】
- 第一行: 最小的可行费用.
【分析】
这是一道动态规划的题目,设长宽分别为l与w。
首先,我们进行预处理,将矩阵按照l递减(主关键字),w递增(次关键字)的顺序排序,
很容易看到的是,如果有两个矩阵i和j,满足l[j]>l[i]并且w[j]>w[i],那么这个矩阵可以完全删除掉,因为在买这个大矩阵j的同时可以把i也顺带买了,这样可以保证排序是唯一确定的。
接下来,设f(i)为前i个矩阵所需要的最小花费,得到朴素递推方程:
f[i]=min{f[j]+l[j+1]*w[i]}(j<i)
复杂度是O(n^2),显然会超时。
考虑斜率优化:
现在有两个决策f[j]与f[k],其中j<k。
假设f[i]从f[j]转移过来比从f[k]转移过来要更优,即:
f[j]+l[j+1]*w[i]<f[k]+l[k+1]*w[i]
两边移一下,得到:
W[i]<(f[k]-f[j])/(l[j+1]-l[k+1])
为了方便,我们不妨将l数组往前提一位(即l[i]=l[i+1]),
设g[j,k] = (f[k]-f[j])/(l[j] - l[k])
则如果g[j,k] > w[i] 表示j比k更优。则k可以舍弃掉。
进而我们发现,当c < b < a < i时,如果有g[c, b] > g[b, a],那么b永远都不会成为计算f[i]时的决策点,为什么呢?
证明:
如果g[c, b] > g[b, a],那么我们可以分两个方面考虑g[c, b]与的关系:
(1)如果g[c, b] > =y[i],那么决策c不会比决策b差,也就说决策b不可能是决策点
(2)如果g[c, b] < y[i],那么由于g[c, b] > g[b, a],那么g[b, a] < y[i],那么决策a要比决策b好,所以b也不能作为决策点。
我们用一个队列来实现上面的规则,使得时间复杂度下降。
我们现在在满足以上性质的一个队列Q中插入一个新的矩阵i.
1、我们要判断第一个条件,得到:
w[i]*(l[Q[front]]-l[Q[front+1]])>(f[Q[front+1]]-f[Q[front]])
如果成立,说明上面的公式说明的是g[front,front+1]<w[i],即front+1要优于front,所以把front踢出队列,直到不可以再踢进行状态的转移。
2、我们要判断第二个条件,得到:
(l[Q[rear]]-l[i])*(f[Q[rear]]-f[Q[rear-1]])>(l[Q[rear-1]]-l[Q[rear]])*(f[i]-f[Q[rear]])
说明的是对于i,rear,rear-1三个元素来说,有g[rear-1,rear]<g[rear,i],显然,把rear踢出队列,直到不可以再踢时在队尾插入i。
显然对于每个元素来说,都要一次插入与一次弹出,所以复杂度为O(n)。
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
const int maxn=;
const int INF=0x7fffffff;
using namespace std;
struct matrix
{
long long l,w;//长与宽
//重载运算符
bool operator <(const matrix &b)const
{
if (l==b.l) return b.w<w;
return b.l<l;
}
}data[maxn];
long long l[maxn],w[maxn],f[maxn];
int Q[maxn];//Q代表队列 int main()
{
int i,j,n,cnt=;
memset(l,,sizeof(l));
memset(w,,sizeof(w));
memset(f,,sizeof(f)); scanf("%d",&n);
for (i=;i<=n;i++) scanf("%lld%lld",&data[i].l,&data[i].w);
sort(data+,data++n);//长度递减
for (i=;i<=n;i++)
//代表高度需要递增
if (cnt== || data[i].w>w[cnt])
{
cnt++;
w[cnt]=data[i].w;
l[cnt]=data[i].l;
}
for(i=;i<cnt;i++) l[i]=l[i+];//千万要注意! int front=,rear=;
Q[]=;
for (i=;i<=cnt;i++)
{
while (front<rear && w[i]*(l[Q[front]]-l[Q[front+]])>(f[Q[front+]]-f[Q[front]]))
front++;
f[i]=f[Q[front]]+l[Q[front]]*w[i];
while (front<rear && (l[Q[rear]]-l[i])*(f[Q[rear]]-f[Q[rear-]])>(l[Q[rear-]]-l[Q[rear]])*(f[i]-f[Q[rear]]))
rear--;
Q[++rear]=i;
} printf("%lld\n",f[cnt]);
return ;
}
【Usaco2008 Mar】土地购买的更多相关文章
- BZOJ 1597: [Usaco2008 Mar]土地购买 [斜率优化DP]
1597: [Usaco2008 Mar]土地购买 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 4026 Solved: 1473[Submit] ...
- 1597: [Usaco2008 Mar]土地购买
1597: [Usaco2008 Mar]土地购买 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 4023 Solved: 1470[Submit] ...
- 【斜率DP】bzoj1597: [Usaco2008 Mar]土地购买
1597: [Usaco2008 Mar]土地购买 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2474 Solved: 900[Submit][ ...
- 【BZOJ 1597】 [Usaco2008 Mar]土地购买 (斜率优化)
1597: [Usaco2008 Mar]土地购买 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3601 Solved: 1322 Descrip ...
- BZOJ 1597: [Usaco2008 Mar]土地购买( dp + 斜率优化 )
既然每块都要买, 那么一块土地被另一块包含就可以不考虑. 先按长排序, 去掉不考虑的土地, 剩下的土地长x递增, 宽y递减 dp(v) = min{ dp(p)+xv*yp+1 } 假设dp(v)由i ...
- BZOJ 1597: [Usaco2008 Mar]土地购买【斜率优化+凸包维护】
1597: [Usaco2008 Mar]土地购买 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 4989 Solved: 1847[Submit] ...
- bzoj1597[Usaco2008 Mar]土地购买 斜率优化dp
1597: [Usaco2008 Mar]土地购买 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 5524 Solved: 2074[Submit] ...
- 【bzoj1597】[Usaco2008 Mar]土地购买
1597: [Usaco2008 Mar]土地购买 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3739 Solved: 1376[Submit] ...
- BZOJ 1597: [Usaco2008 Mar]土地购买 斜率优化
1597: [Usaco2008 Mar]土地购买 Time Limit: 10 Sec Memory Limit: 162 MB Description 农夫John准备扩大他的农场,他正在考虑N ...
- 1597: [Usaco2008 Mar]土地购买 [ dp+斜率优化 ] 未完
传送门 1597: [Usaco2008 Mar]土地购买 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1979 Solved: 705[Subm ...
随机推荐
- mysql 安装1
Linux 安装mysql.tar.gz包(2012-09-28 19:25:06) 标签: it 分类: linux学习编 我用的mysql的版本的是:mysql--linux-i686-icc-g ...
- vector::erase returns incompatible iterator in debug build
关于std::vector中erase的用法http://www.cplusplus.com/reference/vector/vector/erase/ #include <vector> ...
- getElementById返回的是什么?串讲HTML DOM
1. getElementById()返回的是什么? 这个函数使用的最普遍,但是你有没有深入探究下,这个函数究竟返回的是什么么?我们来一起看看. var mydivEle = document.get ...
- java工作流bpm开发ERP实例
今天看了一个java工作流bpm开发ERP的例子,文章介绍:http://tech.it168.com/a2009/0507/275/000000275294_14.shtml 增加数据块 一路照做就 ...
- FusionCharts(v3.6.0)使用(1)
前段时间做一个统计系统,需要画各种图表,于是找到了FusionCharts这个插件,功能甚是强大.在这个闲暇的春日午后,将这个插件的快速使用的方法写下来,方便懒得去官网看英文的朋友参考 安装 Fusi ...
- 【索引】用PS3手柄在安卓设备上玩游戏系列
谈安卓游戏对手柄的支持:http://www.cnblogs.com/duxiuxing/p/3729802.html 连接手柄和设备:http://www.cnblogs.com/duxiuxing ...
- flex与C# Socket通信
原文地址:http://blog.csdn.net/LX10752p/archive/2011/04/27/6366526.aspx Socket 通信没什么好说,一个服务端,多个客户端,很容易搭建环 ...
- How many ways?? - hdu2157(矩阵快速幂-模板)
分析:求Map^k,刚开始没有用快速幂,TLE了 代码如下: =================================================================== ...
- VC++ 动态检测串口的热插拔(一)通过注册表实现
在上一篇文章中讲述了如何通过循环遍历的方法获取可用串口,可是这样的方法过于暴力,难免会想有没有其他的办法那,嘿嘿,那是肯定会有的,不管什么问题,解决问题的方法永远都不止一种.下面讲述如何通过注册表来获 ...
- Python里的map、reduce、filter、lambda、列表推导式
Map函数: 原型:map(function, sequence),作用是将一个列表映射到另一个列表, 使用方法: def f(x): return x**2 l = range(1,10) map( ...