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 }