2009 广东省省赛 D题 a carnival game

该题没有地方提交,不知道能否AC,样例已过

  1 #include <cstdio>
  2 #include <cmath>
  3 
  4 const double eps  = 1.0e-6;
  5 
  6 struct point
  7 {
  8     double x,y;
  9 };
 10 
 11 struct sector
 12 {
 13     point o,a,ca;
 14     double R;
 15 }s[5005];
 16 
 17 int ans[25];
 18 
 19 int k;
 20 
 21 double getdis(point a, point b)
 22 {
 23     return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
 24 }
 25 
 26 double multiply(point p1, point p2, point o)
 27 {
 28     double x1 = p1.x - o.x;
 29     double y1 = p1.y - o.y;
 30     double x2 = p2.x - o.x;
 31     double y2 = p2.y - o.y;
 32     return x1*y2 - x2*y1;
 33 }
 34 
 35 double ptol(point a, point b, point d)
 36 {
 37     return fabs(multiply(a,b,d)) / getdis(a,b);
 38 }
 39 
 40 point getvec(point a, point b, double d)  
 41 {
 42     point t;
 43     t.x = b.y - a.y;
 44     t.y = a.x - b.x;
 45     double k = d/sqrt(t.x*t.x + t.y*t.y);
 46     t.x = t.x*k;
 47     t.y = t.y*k;
 48     return t;
 49 }
 50 
 51 point getcen(point a, point b, double d)   //根据弦求圆心坐标,有两个解
 52 {
 53     point v = getvec(a,b,d);
 54     v.x = (a.x + b.x)*0.5 + v.x;
 55     v.y = (a.y + b.y)*0.5 + v.y;
 56     return v;
 57 }
 58 
 59 struct seg
 60 {
 61     double l,r;
 62 }segs[5005];
 63 
 64 int findans(sector sec, point coin, double r)
 65 {
 66     double tmp = sec.R/k;
 67     for(int i=1; i<=k; i++)
 68     {
 69         segs[i].l = (i-1)*tmp;
 70         segs[i].r = i*tmp;
 71     }
 72     if (sec.R/k/2.0 < r + eps) // coin直径大于两弧间隔距离则肯定为0
 73         return 0;
 74     double dis2 = getdis(sec.o,coin);
 75     if (dis2 >= r + eps && dis2 + r + eps <= sec.R) // 判断coin是否在sector所构成的圆以内
 76     {
 77         if (multiply(coin,sec.a,sec.o) <= -eps && multiply(coin,sec.ca,sec.o) >= eps) // 判断圆心是否在扇形的两相交边之间
 78         {
 79             if (ptol(sec.o,sec.a,coin) >= eps + r && (ptol(sec.o,sec.ca,coin) >= eps + r)) // 判断是否与与两相交边相交
 80             {
 81                 double a = dis2 - r, b = dis2 + r;
 82                 int front = 1 , tail = k, mid;
 83                 mid = (front + tail) / 2; // 二分查找出包含coin的区间
 84                 while (front <= tail)
 85                 {
 86                     if (segs[mid].l + eps <= dis2 - r && dis2 + r + eps <= segs[mid].r)
 87                     {
 88                         break;
 89                     }
 90                     else if (segs[mid].l + eps > dis2 - r)
 91                     {
 92                         tail = mid - 1;
 93                     }
 94                     else
 95                     {
 96                         front = mid + 1;
 97                     }
 98                     mid = (front + tail) / 2;
 99                 }
100                 if (segs[mid].l + eps <= dis2 - r && dis2 + r + eps <= segs[mid].r)
101                     return mid;
102                 else
103                     return 0;
104             }
105         }
106     }
107     return 0;
108 }
109 
110 int main(void)
111 {
112     int t;
113     scanf("%d",&t);
114     for(int cas = 1; cas <= t; cas++)
115     {
116         int n;
117         scanf("%d%d",&n,&k);
118         for(int i=1; i<=n; i++)
119         {
120             scanf("%lf%lf%lf%lf%lf",&s[i].a.x,&s[i].a.y,&s[i].ca.x,&s[i].ca.y,&s[i].R);
121             // 根据弦和半径求出圆心,注意求出的是两个需要找出正确的
122             double dis = s[i].R*cos(asin(getdis(s[i].a,s[i].ca)/2/s[i].R));
123             point t1 = getcen(s[i].a,s[i].ca,dis);
124             point t2 = getcen(s[i].ca,s[i].a,dis);
125             if (multiply(s[i].ca,s[i].a,t1) < 0)
126                 s[i].o = t1;
127             else
128                 s[i].o = t2;
129         }
130         double r;
131         point coin;
132         int q;
133         scanf("%d",&q);
134         for(int cc = 1; cc<=q; cc++)
135         {
136             ans[cc] = 0;
137             scanf("%lf%lf%lf",&coin.x,&coin.y,&r);
138             for(int i=1; i<=n; i++)
139             {
140                 ans[cc] = findans(s[i],coin,r);
141                 if (ans[cc])
142                 {
143                     ans[cc] = k+1-ans[cc];
144                     break;
145                 }
146             }
147         }
148         printf("Case %d:\n",cas);
149         for(int cc=1; cc<=q; cc++)
150             printf("%d\n",ans[cc]);
151     }
152     return 0;
153 }

 

posted @ 2014-04-12 20:33  辛力啤  阅读(143)  评论(0编辑  收藏  举报