usaco2016open bronze3 reduce

来源:互联网 发布:蒋勤勤的长相知乎 编辑:程序博客网 时间:2024/06/05 22:58

Bronze3

农夫约翰的N(3N50000)头牛被定在了平面内的不同的位置。他想用栅栏(平行于xy)围住所有的牛。他想这个栅栏尽可能小(牛在边界上也被视作围住)

他因为牛奶产量低而感到经费紧张,所以他想卖掉一头牛再围起剩下的牛。请算出栅栏围出的最小面积。

输入:

第一行输入n

剩下2-n+1行,输入每头牛的位置。坐标在1...40000范围内。

输出:
最小面积(矩形)

示例

input

4

2 4

1 1

5 2

17 25

output

12

================================================================

给出在平面直角坐标系上 n 个点的坐标,要求算出去掉一个点之后构造一个把其余点包含在内的矩形的最小面积是多少.显然,在点足够少的情况下,我们可以直接枚举去掉的点,然后求出忽略该点之后 x y 的最大最小值并算出矩形面积,取最小面积即可.但有一个细节,在确定了移除的点之后怎么求其余点中 x y 的最大最小值?如果再用一重循环来找,显然太慢,时间复杂度达到 O(n^2),对于本题而言会超时.显而易见,很容易想到预处理的做法.但如果先求出这四个值,假如我们选定要移除的点的坐标不巧正好在这四个值中有呢?当然,我们也可以在这种情况下重新求一次值,理论上确实是可行的.但考虑一种极端情况:所有点的 x 坐标或 y 标都相同,那么很不幸,算法还是会退化到 O(n^2)级别.因此为了避免这种尴尬情况,我们在预处理的时候求前两大和前两小的值备用,假如最大值/最小值属于要被删除的点,那就可以直接取用第二大/第二小的值即可.时间上没有多大的变化,但却完美解决了之前的困扰.

#include <cstdio>
#define min(a,b) (a<b?a:b)
const int SIZE=5e4+5;
const int INF=0x7fffffff;
int N,x[SIZE],y[SIZE],x1,x2,x3,x4,y1,y2,y3,y4;
void update(int,int);
int main(){
freopen("reduce.in","r",stdin);
freopen("reduce.out","w",stdout);
scanf("%d",&N);
x1=x2=y1=y2=INF;
x3=x4=y3=y4=0;
for(int i=0;i!=N;++i){
scanf("%d%d",&x[i],&y[i]);
update(x[i],y[i]);
}
int ans=(x4-x1)*(y4-y1);
for(int i=0;i!=N;++i){
int xMin=(x[i]==x1?x2:x1);
int xMax=(x[i]==x4?x3:x4);
int yMin=(y[i]==y1?y2:y1);
int yMax=(y[i]==y4?y3:y4);
ans=min(ans,(xMax-xMin)*(yMax-yMin));
}
printf("%d\n",ans);
return 0;
}
void update(int x,int y){
if(x<x1){x2=x1;x1=x;}else if(x<x2)x2=x;
if(x>x4){x3=x4;x4=x;}else if(x>x3)x3=x;
if(y<y1){y2=y1;y1=y;}else if(y<y2)y2=y;
if(y>y4){y3=y4;y4=y;}else if(y>y3)y3=y;
}

0 0
原创粉丝点击