https://vjudge.net/problem/UVA-1382
题意:
给出平面上的n个点,找出一个矩形,使得边界上包含尽量多的点。
思路:
参考训练指南。
首先如果枚举起起点,终点,再进行统计的话,复杂度显然太大了,因为坐标的范围是10的9次方级别的。
所以,又想到扫描线的方法。
我们首先对数组排个序,枚举上下边界,之后,用三个数组,left[i]表示i这条线左边(不包括这条线)的在上下边界的点的数量,on[i]表示在i这条线上的位于上下边界之间的点的数量(不包括上下边界),on2[i]表示,
在i这条线上的位于上下边界之间的点的数量(包括上下边界),我们从左往右扫一遍,维护这三个数组的信息。
left[i] = left[i-1] + on2[i] - on[i-1],在i-1这条边的左边的在上下边界上的点的数量等于它上一条边的左边的在上下边界上的点的数量加上上一条边的在上下边界上的点的数量,on2[i-1] - on[i-1]就是位于上下边界的点的数量。
ans = max(left[i] + on2[i]+on[k] - left[k])(k < i),我们要维护的就是on[k] - left[k]的最大值,在从左往右扫的时候维护。
一些细节的处理需要注意,比如点都在一条边或者两条边上。
代码:
1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 using namespace std; 5 6 struct node 7 { 8 int x,y; 9 } a[105]; 10 11 int n,m; 12 13 int y[105]; 14 int left[105],on[105],on2[105]; 15 16 bool cmp(node aa,node bb) 17 { 18 return aa.x < bb.x; 19 } 20 21 int solve(void) 22 { 23 sort(a,a+n,cmp); 24 25 int ans = 0; 26 27 sort(y,y+n); 28 29 m = unique(y,y+n) - y; 30 31 if (m <= 2) return n; 32 33 for (int i = 0;i < m;i++) 34 for (int j = i + 1;j < m;j++) 35 { 36 int ymin = y[i],ymax = y[j]; 37 38 int num = 0; 39 40 for (int k = 0;k < n;k++) 41 { 42 if (k == 0 || a[k].x != a[k-1].x) 43 { 44 num++; 45 46 on[num] = on2[num] = 0; 47 48 left[num] = num == 0 ? 0 : left[num-1] + on2[num-1] - on[num-1]; 49 } 50 51 52 if (a[k].y > ymin && a[k].y < ymax) on[num]++; 53 if (a[k].y >= ymin && a[k].y <= ymax) on2[num]++; 54 } 55 56 if (num <= 2) return n; 57 58 int M = 0; 59 60 for (int k = 1;k <= num;k++) 61 { 62 ans = max(ans,M + left[k] + on2[k]); 63 M = max(M,on[k] - left[k]); 64 } 65 } 66 67 return ans; 68 } 69 70 int main() 71 { 72 int kase = 0; 73 74 while (scanf("%d",&n) != EOF) 75 { 76 if (!n) break; 77 78 for (int i = 0;i < n;i++) 79 { 80 scanf("%d%d",&a[i].x,&a[i].y); 81 82 y[i] = a[i].y; 83 } 84 85 int ans = solve(); 86 87 printf("Case %d: %d ",++kase,ans); 88 } 89 90 return 0; 91 }