#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define PI 3.14159265359
#define eps 1e-8
using namespace std;
struct Point
{
int x,y,r;
double ang;
} rem[1005],v[1005];
int n;
int cmp(const struct Point a,const struct Point b) //按角度排序(極角排序)
{
if (a.ang < b.ang)
return 1;
else return 0;
}
int sig(double a) //判斷當前是否滿足精度 0滿足 1不滿足 -1等於精度
{
if (fabs(a) < eps)
return 0;
else if (a > 0)
return 1;
else return -1;
}
int cross(struct Point a,struct Point b,struct Point c) //叉積
{
return (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y);
}
int main()
{
while (scanf("%d",&n) && n)
{
int ans = 0;
for (int i = 1; i <= n; ++i)
{
scanf("%d%d%d",&v[i].x,&v[i].y, &v[i].r);
rem[i] = v[i]; //rem 存放最原始的數據
}
for (int i = 1; i <= n; ++i) //****枚舉每個點做旋轉點
{
for (int j = 1; j <= n; ++j) //對v賦值 對於屬性是0的點,直接賦值,屬性爲1的點,對稱賦值. 並計算角度
{
v[j] = rem[j];
if (v[j].r == 1) //如果是屬性是1的點 對稱到 直線的 另一端
{
v[j].x = rem[i].x * 2 - v[j].x;
v[j].y = rem[i].y * 2 - v[j].y;
}
v[j].ang = atan2(v[j].y - rem[i].y , v[j].x - rem[i].x); //計算弧度
}
swap(v[i],v[1]); //v[1]總是當前枚舉的點 所以不斷的交換v[i] 值與v[1]值
sort(v + 2, v + n + 1, cmp); //****極角排序
//開始點,已經有2個,v[1]和v[2] 然後對第三個點進行考慮
for(int s = 2,t = 3; s <= n && sig(v[s].ang) <= 0; s++) //****當前直線由v[1]和v[s]兩點確定(選取直線,旋轉掃描)
{
int on = 2; //on是直線上點的個數
for ( ; t <= n && cross(v[1],v[s],v[t]) >= 0; t++) //只判斷一側的點,t統計的是在一側的點
{
if (cross(v[1],v[s],v[t]) == 0) //三點共線 在icpc線上
on++; //線上點+1
}
//t-s-1:0側溶解0,1側溶解0的情況能得到的值 n-(t-s+1)+on 0側溶解1,1側溶解0
ans = max(ans , max(t - s + 1, n - (t - s + 1) + on));
}
}
printf("%d\n",ans);
}
return 0;
}
POJ 2280 幾何題 經典 枚舉+極角排序+旋轉掃描
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.