POJ2280 Amphiphilic Carbon Molecules

完全不會計算幾何。。。不過這題雖然是查別人的題解的,但是還是值得寫一下題解來進一步解釋一下。

思路是枚舉一個基準點,將基準點到所有其他的點的向量按照極角排序,然後依次將每一個向量作爲一種放置方法(下面把這個取出來作爲基準的向量叫做基準向量,ICPC放在與基準向量共線的直線上,從向量的方向看過去,向量所在直線的左側溶解color爲0的點)掃描這種放置方式下溶解的點的數目。這裏有個非常巧妙的地方,將color爲1的點放到關於基準點對稱的位置上,那麼我們掃描時只需要將掃描向量從基準向量開始旋轉180°記錄下所有掃描線經過的點即可。

同時,當基準向量旋轉時,只需要從上次掃描向量停下來的地方開始掃描,同時減去基準向量轉過的區域內包括的點即可(由於基準向量每次只移動一個點,所以每次移動基準向量時,點的數目要在原先的基礎上減去1,當掃描向量與基準向量重合的時候(這種情況是存在的:當所有的點全都共線的時候以第一個點作爲基準點,每次移動基準向量,掃描向量都是從與基準向量重合的位置開始掃描的。),可以視爲是剛開始掃描,先加上一個點後在掃描完成後減去,以與之前的過程保持一致)

AC代碼如下:

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;

struct point
{
	int x,y;
	double rad;
	point(int xx=0,int yy=0,double r=0.0):x(xx),y(yy),rad(r){}
	bool operator< (const point &a)const
	{
		return rad<a.rad;
	}
};

point p[10005],v[10005];
int color[10005];

bool left(point a,point b)
{
	return a.x*b.y-a.y*b.x>=0;
}

int main(int argc, char const *argv[])
{
	int n;
	while(scanf("%d", &n)&&n!=0)
	{
		for(int i=0;i<n;i++)
		{
			scanf("%d %d %d", &p[i].x,&p[i].y, &color[i]);
		}  
		int ans=0;
		for(int i=0;i<n;i++)
		{
			int k=0;
			for(int j=0;j<n;j++)
			{
				if(j!=i)
				{
					v[k].x=p[j].x-p[i].x;
					v[k].y=p[j].y-p[i].y;
					if(color[j])
					{
						v[k].x=-v[k].x;
						v[k].y=-v[k].y;
					}
					v[k].rad=atan2((double)v[k].y,(double)v[k].x);
					k++;
				}
			}
			if(k<=2)
			{
				ans=n;
				break;
			}
			sort(v,v+k);
			int L=0,R=0,cnt=2;
			for(L=0;L<k;L++)
			{
				if(L==R)
				{	
					R=(R+1)%k;
					cnt++;
				}
				while(L!=R&&left(v[L],v[R]))
				{
					R=(R+1)%k;
					cnt++;
				}
				cnt--;
				ans=max(ans,cnt);
			}
		}
		printf("%d\n", ans);
	}
	return 0;
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章