P1578 奶牛浴场(极大化思想)

题目描述

由于John建造了牛场围栏,激起了奶牛的愤怒,奶牛的产奶量急剧减少。为了讨好奶牛,John决定在牛场中建造一个大型浴场。但是John的奶牛有一个奇怪的习惯,每头奶牛都必须在牛场中的一个固定的位置产奶,而奶牛显然不能在浴场中产奶,于是,John希望所建造的浴场不覆盖这些产奶点。这回,他又要求助于Clevow了。你还能帮助Clevow吗?

John的牛场和规划的浴场都是矩形。浴场要完全位于牛场之内,并且浴场的轮廓要与牛场的轮廓平行或者重合。浴场不能覆盖任何产奶点,但是产奶点可以位于浴场的轮廓上。

Clevow当然希望浴场的面积尽可能大了,所以你的任务就是帮她计算浴场的最大面积。

输入输出格式

输入格式:
输入文件的第一行包含两个整数L和W,分别表示牛场的长和宽。文件的第二行包含一个整数n,表示产奶点的数量。以下n行每行包含两个整数x和y,表示一个产奶点的坐标。所有产奶点都位于牛场内,即:0<=x<=L,0<=y<=W。

输出格式:
输出文件仅一行,包含一个整数S,表示浴场的最大面积。

输入输出样例

输入样例#1:
10 10
4
1 1
9 1
1 9
9 9
输出样例#1:
80
说明

0<=n<=5000

1<=L,W<=30000

三、 极大化思想
【定理1】在一个有障碍点的矩形中的最大子矩形一定是一个极大子矩形。
证明:如果最大子矩形A不是一个极大子矩形,那么根据极大子矩形的定义,存在一个包含A且比A更大的有效子矩形,这与“A是最大子矩形”矛盾,所以【定理1】成立。

定理2】:一个极大子矩形的四条边一定都不能向外扩展。更进一步地说,一个有效子矩形是极大子矩形的充要条件是这个子矩形的每条边要么覆盖了一个障碍点,要么与整个矩形的边界重合。

【定理3】:如果将一个悬线向左右两个方向尽可能移动所得到的有效子矩形称为这个悬线所对应的子矩形,那么所有悬线所对应的有效子矩形的集合一定包含了所有极大子矩形的集合。

根据【定理3】可以发现,通过枚举所有的悬线,就可以枚举出所有的极大子矩形。由于每个悬线都与它底部的那个点一一对应,所以悬线的个数=(n-1)×m(以矩形中除了顶部的点以外的每个点为底部,都可以得到一个悬线,且没有遗漏)。如果能做到对每个悬线的操作时间都为O(1),那么整个算法的复杂度就是O(NM)。这样,我们看到了解决问题的希望。

program df;
type     point=record
x,y:longint;
end;
var i,j,n,m,z,k,t,up,down,ans,w:longint;
a,b:array[0..100000] of point;

procedure sq(l,r:longint);
var i,j,mm:longint;
dd:point;
begin
i:=l; j:=r;
mm:=a[(l+r) div 2].x;
repeat
while a[i].x<mm do inc(i);
while a[j].x>mm do dec(j);
if i<=j then
begin
dd:=a[i]; a[i]:=a[j]; a[j]:=dd;
inc(i); dec(j);
end;
until i>j;
if l<j then sq(l,j);
if i<r then sq(i,r);
end;

begin
readln(z,w);
readln(n);

for i:=1 to n do
readln(a[i].x,a[i].y);
a[n+1].x:=z; a[n+1].y:=w;
a[n+2].x:=z; a[n+2].y:=0;
a[n+3].x:=0; a[n+3].y:=w;
a[n+4].x:=0; a[n+4].y:=0;

sq(1,n+4);
ans:=0;

for i:=1 to n+3 do
begin
up:=w; down:=0;
for j:=i+1 to n+4 do
begin
if (a[i].x=a[j].x) or (a[j].y>up) or (a[j].y<down) then continue;

if (up-down)*(a[j].x-a[i].x)>ans then 
ans:=(up-down)*(a[j].x-a[i].x);

if (a[j].y>=a[i].y) and (a[j].y<up) then up:=a[j].y;
if (a[j].y<=a[i].y) and (a[j].y>down) then down:=a[j].y;
if up<=down then break;
end;
end;
writeln(ans);
end.

转载于:https://www.cnblogs.com/Gxyhqzt/p/7784245.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值