1. 程式人生 > >UVA - 1606 Amphiphilic Carbon Molecules (計算幾何,掃描法)

UVA - 1606 Amphiphilic Carbon Molecules (計算幾何,掃描法)

尺取法 rbo bits code 部分 ace spa 指針 網上

平面上給你一些具有黑或白顏色的點,讓你設置一個隔板,使得隔板一側的黑點加上另一側的白點數最多。隔板上的點可視作任意一側。

易知一定存在一個隔板穿過兩個點且最優,因此可以先固定以一個點為原點,將其他點中的黑點移到對稱的位置,並將所有點按極角排序,然後雙指針遍歷其他點,利用尺取法維護一個角度不超過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 }

UVA - 1606 Amphiphilic Carbon Molecules (計算幾何,掃描法)