EOJ:Circle Artwork
Circle Artwork
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submits: 48 | Accepted: 6 |
Description
Circle is an ancient and universal symbol of unity, wholeness, infinity, the goddess, and female power. It is referenced frequently in religion and art. In this problem, we act as a modern artist and would like to draw our painting with points and circles, and clearly colors should be used. First, we put some colored points on the canvas. The goal is to draw a circle for each color Ci, such that every colored point inside or on the boundary of that circle has color Ci. Also, each such circle should have at least two points on its boundary. Note that for some colors, it might be impossible to draw such a circle. In this problem, given a set of colored points, your task is to compute the largest number of colors for which there exists a circle conforming to the above conditions.
Input
There are multiple test cases in the input. For each test case, in the first line there is a positive integer n (1 ≤ n ≤ 100), which is the number of colored points. This is followed by n lines of the form Ci Xi Yi where Ci is the color of the ith point and Xi Yi specify its coordinates. Each color string is made up of at most 20 small English letters. Coordinates are integers between -1,000,000 and 1,000,000. The last line of each test case contains a single 0.
Output
For each test case, write a single line which contains the largest number of colors for which there exists a circle conforming to the above conditions.
Sample Input
4 red 1 1 blue 1 2 blue 3 2 yellow 3 3 0
Sample Output
1
http://202.120.106.94/onlinejudge/problemshow.php?pro_id=84
__________________________________________________________________________________________________________
此题精妙之处在于运用了四点共圆的推论。
枚举两个同色的点,然后再枚举与这两点不同色的点,不同色的点分为两类,在同色点连成线的左边或右边。(叉积判断)
令a为左边的点与两个同色点形成的最大张角,b为右边的最大张角,由四点共圆的推论可知当a+b<pi的时候,这两个同色点形成的圆内部没有其他颜色的点。
另外ON_SEGMENT是三点共线的特判,理论上应该可以和上面的情况合并。
最大张角由叉积来算:tan x=(a×b)÷(a·b) (a,b均为向量)
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<string.h>
4 #include<math.h>
5 #define eps 1e-8
6 struct node
7 {
8 char clor[30];
9 int x,y;
10 }dot[105];
11 const double pi=acos(-1.);
12 int i,j,k,n,ans;
13 double ang1,ang2,_cross,_dot,ang;
14 bool flag;
15 double max(double a,double b)
16 {
17 return a>b?a:b;
18 }
19 double min(double a,double b)
20 {
21 return a>b?b:a;
22 }
23 int cmp(const void *a,const void *b)
24 {
25 struct node *x=(node *)a;
26 struct node *y=(node *)b;
27 return strcmp(x->clor,y->clor);
28 }
29 double cal_cross(double x1,double y1,double x2,double y2,double x3,double y3)
30 {
31 return (x1-x3)*(y2-y3)-(x2-x3)*(y1-y3);
32 }
33 double cal_dot(double x1,double y1,double x2,double y2,double x3,double y3)
34 {
35 return (x1-x3)*(x2-x3)+(y1-y3)*(y2-y3);
36 }
37 bool on_segment(double x1,double y1,double x2,double y2,double x3,double y3)
38 {
39 double X1,X2,Y1,Y2;
40 X1=min(x1,x2);
41 X2=max(x1,x2);
42 Y1=min(y1,y2);
43 Y2=max(y1,y2);
44 if (X1<=x3&&x3<=X2&&Y1<=y3&&y3<=Y2) return false;
45 return true;
46 }
47 int main()
48 {
49 while (1)
50 {
51 ans=0;
52 scanf("%d",&n);
53 if (n==0) break;
54 getchar();
55 for (i=0;i<n;i++)
56 scanf("%s%d%d",&dot[i].clor,&dot[i].x,&dot[i].y);
57 qsort(dot,n,sizeof(dot[0]),cmp);
58 flag=false;
59 for (i=0;i<n;i++)
60 {
61 if (i!=0&&strcmp(dot[i].clor,dot[i-1].clor)==0&&flag) continue;
62 flag=true;
63 for (j=i+1;j<n;j++)
64 {
65 ang1=0;
66 ang2=0;
67 if (strcmp(dot[i].clor,dot[j].clor)!=0) break;
68 for (k=0;k<n;k++)
69 if (strcmp(dot[i].clor,dot[k].clor)!=0)
70 {
71 _cross=cal_cross(dot[i].x,dot[i].y,dot[j].x,dot[j].y,dot[k].x,dot[k].y);
72 _dot=cal_dot(dot[i].x,dot[i].y,dot[j].x,dot[j].y,dot[k].x,dot[k].y);
73 ang=fabs(atan2(_cross,_dot));
74 if (_cross>0)
75 ang1=max(ang1,ang);
76 else
77 if (_cross<0)
78 ang2=max(ang2,ang);
79 else
80 if (!on_segment(dot[i].x,dot[i].y,dot[j].x,dot[j].y,dot[k].x,dot[k].y))
81 flag=false;
82 if (ang1+ang2>=pi)
83 flag=false;
84 if (!flag) break;
85 }
86 if (flag)
87 {
88 ans++;
89 break;
90 }
91 }
92 }
93 printf("%d\n",ans);
94 }
95 }