填坑系列
考虑所有经过两个点的直线,一定有最优解。
再考虑确定一个点,按极角顺序枚举所有直线,从而O(1)转移信息。
还有代码实现技巧
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<algorithm> 5 #include<iostream> 6 7 const int N = 1000 + 10; 8 9 typedef const struct Point& CP; 10 struct Point { 11 int x, y; 12 double rad; 13 bool operator < (CP rhs) const { 14 return rad < rhs.rad; 15 } 16 }op[N], p[N]; 17 18 int n, color[N]; 19 20 bool Left(CP a, CP b) { 21 return a.x * b.y - a.y * b.x >= 0; 22 } 23 24 #include<cmath> 25 int solve() { 26 if(n <= 2) return n; 27 int ans = 0; 28 29 for(int i = 0; i < n; i++) { 30 int k = 0; 31 for(int j = 0; j < n; j++) if(i ^ j) { 32 p[k].x = op[j].x - op[i].x; 33 p[k].y = op[j].y - op[i].y; 34 if(color[j]) { 35 p[k].x = -p[k].x; 36 p[k].y = -p[k].y; 37 } 38 p[k].rad = atan2(p[k].y, p[k].x); 39 k++; 40 } 41 std::sort(p, p + k); 42 43 int L = 0, R = 0, cnt = 1; 44 while(L < k) { 45 if(R == L) { 46 ++R %= k; 47 cnt++; 48 } 49 while(R != L && Left(p[L], p[R])) { 50 ++R %= k; 51 cnt++; 52 } 53 ans = std::max(ans, cnt); 54 L++, cnt--; 55 } 56 } 57 return ans; 58 } 59 60 int main() { 61 #ifdef DEBUG 62 freopen("in.txt", "r", stdin); 63 freopen("out.txt", "w", stdout); 64 #endif 65 66 while(scanf("%d", &n) == 1 && n) { 67 for(int i = 0; i < n; i++) { 68 scanf("%d%d%d", &op[i].x, &op[i].y, color + i); 69 } 70 printf("%d\n", solve()); 71 } 72 73 return 0; 74 }
时间: 2024-09-17 06:42:02