标签:
任意线可以贪心移动到两点上。直接枚举O(n^3),会TLE。
所以采取扫描法,选基准点,然后根据极角或者两两做叉积比较进行排排序,然后扫一遍就好了。旋转的时候在O(1)时间推出下一种情况,总复杂度为O(n^2logN)就可以过了。
另外,本题有个很巧妙的技巧,就是一点等效与相反坐标的相反颜色的点。
第一次写,细节还是蛮多的,花了好久才搞清所有细节。。。
极角排序版,比较容易理解,932ms。
#include<bits/stdc++.h> using namespace std; const int maxn = 1003; struct Point { int x,y; double rad; bool operator<(const Point &rhs) const { return rad < rhs.rad; } }P[maxn]; int col[maxn]; Point tmp[maxn]; bool cmp(const Point& a,const Point& b) //anticlockwise sort { return a.x*b.y >= b.x*a.y; } int solve(int n) { if(n<=3) return n; int ans = -1; for(int pivot = 0; pivot < n; pivot++){ int k = 0; for(int i = 0; i < n; i++) if(i!=pivot){ tmp[k].x = P[i].x - P[pivot].x; tmp[k].y = P[i].y - P[pivot].y; if(col[i]) { tmp[k].x = - tmp[k].x; tmp[k].y = -tmp[k].y; } tmp[k].rad = atan2(tmp[k].y, tmp[k].x); k++; } sort(tmp,tmp+k); int L = 0, R = 0, sum = 1; while(L<k){ if(L == R) { R = (R+1)%k; sum++; } while(R != L && cmp(tmp[L],tmp[R])) { R = (R+1)%k; sum++; } ans = max(ans,sum); sum--; L++; } } return ans; } int main() { int n; while(~scanf("%d",&n)&&n){ for(int i = 0; i < n; i++) scanf("%d%d%d",&P[i].x,&P[i].y,col+i); printf("%d\n",solve(n)); } return 0; }
如果卡精度,那么就用叉积两两比较,算极角常数大一些,叉积跑的快一点577ms。
#include<bits/stdc++.h> using namespace std; const int maxn = 1003; struct Point { int x,y,col; }P[maxn],tmp[maxn];; inline int cross(const Point& a,const Point& b) { return a.x*b.y - b.x*a.y; } bool cmp(const Point& a,const Point& b) //anticlockwise sort { return a.x*b.y > b.x*a.y; } int solve(int n) { if(n<=3) return n; int ans = -1; for(int pivot = 0; pivot < n; pivot++){ int k = 0; for(int i = 0; i < n; i++) if(i!=pivot){ tmp[k].x = P[i].x - P[pivot].x; tmp[k].y = P[i].y - P[pivot].y; if(tmp[k].y < 0 || (tmp[k].y == 0 && tmp[k].x < 0) ) { tmp[k].x = - tmp[k].x; tmp[k].y = -tmp[k].y; tmp[k].col = P[i].col^1; }else tmp[k].col = P[i].col; k++; } sort(tmp,tmp+k,cmp); int w = 0,b = 0; int i,j; for(i = 0; i < k; i++) if(tmp[i].col == 0)w++; for( i = 0; i < k; i = j) { int lw = 0; for(j = i; j < k; j++) { if(cross(tmp[i],tmp[j])) break; if(tmp[j].col) b++; else lw++; } ans = max(ans,w+b+1); ans = max(ans,k-w-b+j-i+1); w -= lw; } } return ans; } int main() { int n; while(~scanf("%d",&n)&&n){ for(int i = 0; i < n; i++) scanf("%d%d%d",&P[i].x,&P[i].y,&P[i].col); printf("%d\n",solve(n)); } return 0; }
UVA 1606 Amphiphilic Carbon Molecules 两亲性分子 (极角排序或叉积,扫描法)
标签:
原文地址:http://www.cnblogs.com/jerryRey/p/4693461.html