UVA - 1606 Amphiphilic Carbon Molecules (计算几何,扫描法)

平面上给你一些具有黑或白颜色的点,让你设置一个隔板,使得隔板一侧的黑点加上另一侧的白点数最多。隔板上的点可视作任意一侧。

易知一定存在一个隔板穿过两个点且最优,因此可以先固定以一个点为原点,将其他点中的黑点移到对称的位置,并将所有点按极角排序,然后双指针遍历其他点,利用尺取法维护一个角度不超过180°的区间(算角度是否大于180°可以用叉积)。对每个点都算一遍,取最大区间长度即为最终答案。

区间尺取部分网上的代码基本都的lr表示法,比较冗长,我这里给出了lw表示法(w代表区间长度),代码简洁了许多,只是因为之前忘了在l增加的时候改变w的值而WA到怀疑人生...

另外注意n<=3时需要特判。(貌似只用特判n=1,但n=3的时候答案就是n,可以直接跳过求解过程)

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 typedef long long ll;
 5 typedef double db;
 6 const int N=1000+10;
 7 const db eps=1e-10;
 8 struct P {
 9     int col;
10     db x,y,rad;
11     bool operator<(const P& b)const {return rad<b.rad;}
12 } p[N],q[N];
13 int n,m,ans;
14 db cross(P a,P b) {return a.x*b.y-a.y*b.x;}
15 
16 int main() {
17     while(scanf("%d",&n)&&n) {
18         for(int i=0; i<n; ++i)scanf("%lf%lf%d",&p[i].x,&p[i].y,&p[i].col);
19         if(n<=3)ans=n;
20         else {
21             ans=0;
22             for(int i=0; i<n; ++i) {
23                 m=0;
24                 for(int j=0; j<n; ++j)if(j!=i) {
25                         q[m]= {p[j].col,p[j].x-p[i].x,p[j].y-p[i].y};
26                         if(q[m].col)q[m].x=-q[m].x,q[m].y=-q[m].y;
27                         q[m].rad=atan2(q[m].y,q[m].x);
28                         m++;
29                     }
30                 sort(q,q+m);
31                 for(int l=0,w=0; l<m; ++l,--w) {
32                     for(; w<m&&cross(q[l],q[(l+w)%m])>=0; ++w);
33                     ans=max(ans,w+1);
34                 }
35             }
36         }
37         printf("%d\n",ans);
38     }
39     return 0;
40 }

猜你喜欢

转载自www.cnblogs.com/asdfsag/p/10358065.html