18.03.20 vijos1055奶牛浴场

描述

由于John建造了牛场围栏,激起了奶牛的愤怒,奶牛的产奶量急剧减少。为了讨好奶牛,John决定在牛场中建造一个大型浴场。但是John的奶牛有一个奇怪的习惯,每头奶牛都必须在牛场中的一个固定的位置产奶,而奶牛显然不能在浴场中产奶,于是,John希望所建造的浴场不覆盖这些产奶点。这回,他又要求助于Clevow了。你还能帮助Clevow吗?
John的牛场和规划的浴场都是矩形。浴场要完全位于牛场之内,并且浴场的轮廓要与牛场的轮廓平行或者重合。浴场不能覆盖任何产奶点,但是产奶点可以位于浴场的轮廓上。

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

格式

输入格式

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

输出格式

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

样例1

样例输入1

10 10
4
1 1
9 1
1 9
9 9

样例输出1

80

限制

各个测试点1s

提示

0<=n<=5000
1<=L,W<=30000

来源

Winter Camp 2002

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <stdlib.h>
 4 #include <algorithm>
 5 #include <string.h>
 6 
 7 using namespace std;
 8 
 9 const int maxn=5003;
10 struct node{
11     int x,y;
12 }poi[maxn];
13 bool cmp1(node a,node b){
14     return a.x<b.x;
15 }
16 bool cmp2(node a,node b){
17     return a.y<b.y;
18 }
19 
20 int main()
21 {
22     int l,w;//长;宽
23     int n;//产奶点数量
24     scanf("%d%d%d",&l,&w,&n);
25     for(int i=1;i<=n;i++){
26         scanf("%d%d",&poi[i].x,&poi[i].y);
27     }
28     poi[++n].x=0,poi[n].y=w;
29     poi[++n].x=0,poi[n].y=0;
30     poi[++n].x=l,poi[n].y=0;
31     poi[++n].x=l,poi[n].y=w;//加入边界点
32     sort(poi+1,poi+n+1,cmp1);//横向排序
33     //左边覆盖一个障碍点的情况
34     int maxarea=0;
35     for(int i=1;i<=n;i++){
36         int up=w,bott=0;
37         for(int j=i+1;j<=n;j++){
38              maxarea=max(maxarea,(poi[j].x-poi[i].x)*(up-bott));
39             if(poi[j].y<poi[i].y&&poi[j].y>bott)
40                 bott=poi[j].y;
41             else if(poi[j].y>poi[i].y&&poi[j].y<up)
42                 up=poi[j].y;
43             else if(poi[j].y==poi[i].y)
44                 break;
45         }
46     }
47     //右边覆盖一个障碍点的情况
48     for(int i=n;i>=1;i--){
49         int up=w,bott=0;
50         for(int j=i-1;j>=1;j--){
51              maxarea=max(maxarea,(poi[i].x-poi[j].x)*(up-bott));
52              if(poi[j].y<poi[i].y&&poi[j].y>bott)
53                  bott=poi[j].y;
54              else if(poi[j].y>poi[i].y&&poi[j].y<up)
55                  up=poi[j].y;
56              else if(poi[j].y==poi[i].y)
57                  break;
58         }
59     }
60     //两边都在边界上的情况
61     sort(poi+1,poi+n+1,cmp2);//纵向排序
62     int maxgap=0;
63     for(int i=1;i<n;i++){
64         maxgap=max(maxgap,poi[i+1].y-poi[i].y);
65     }
66     maxarea=max(maxgap*l,maxarea);
67     printf("%d\n",maxarea);
68     return 0;
69 }
View Code

很标准的极大化思想(可用悬线法

看思路点这里

一定要左边扫描一遍右边扫描一遍

再强调一下sort的用法!第二个参数是最后一位再后面一位

以及看到有大佬把除了左边以外的所有情况归结到纵向扫描的方法上去,在这里也贴一下

 1 //作者:孤的千年
 2 //@vijos
 3 #include <stdio.h>
 4 #include <algorithm>
 5 using namespace std;
 6 const int maxn=5005;
 7 
 8 int ans;
 9 int l,w,n;
10 struct node{int x,y;}e[maxn];
11 inline bool cp1(node a,node b){return a.x<b.x;}
12 inline bool cp2(node a,node b){return a.y<b.y;}
13 
14 int main()
15 {
16     scanf("%d%d%d",&l,&w,&n);
17     for(int i=1;i<=n;i++)
18         scanf("%d%d",&e[i].x,&e[i].y);
19     e[++n].x=0,e[n].y=0;
20     e[++n].x=0,e[n].y=w;
21     e[++n].x=l,e[n].y=0;
22     e[++n].x=l,e[n].y=w;
23     sort(e+1,e+n+1,cp1);
24     for(int i=1;i<n;i++)
25     {
26         int u=w,d=0;
27         for(int j=i+1;j<=n;j++)
28         {
29             if(e[j].y>=d && e[j].y<=u)
30             {
31                 ans=max(ans,(e[j].x-e[i].x)*(u-d));
32                 if(e[j].y>e[i].y) u=e[j].y;
33                 else d=e[j].y;
34             }
35             if(u==d) break;
36         }
37     }
38     sort(e+1,e+n+1,cp2);
39     for(int i=1;i<n;i++)
40     {
41         int u=0,d=l;
42         for(int j=i+1;j<=n;j++)
43         {
44             if(e[j].x>=u && e[j].x<=d)
45             {
46                 ans=max(ans,(e[j].y-e[i].y)*(d-u));
47                 if(e[j].x>e[i].x) d=e[j].x;
48                 else u=e[j].x;              
49             }
50             if(u==d) break;
51         }
52     }
53     printf("%d",ans);
54     return 0;
55 }
View Code
posted @ 2018-03-20 15:59  TobicYAL  阅读(292)  评论(0编辑  收藏  举报