zoj 1696 Viva Confetti

来源:互联网 发布:苹果手机炒股软件 编辑:程序博客网 时间:2024/05/01 19:27

我了个去。。。写了一下午,快哭了。

这个题的精度真的是相当相当的恶心!!!
在训练指南上看到这题,思路大家应该都可以想到,枚举所有的弧,然后取弧两边的点(距离弧很近很近的),然后枚举最后是哪个盘子上的。
我的做法是取弧的中间点,然后算个从圆心到中点delta小向量,中点加减这个向量,得到两边的点。
输入是到12位精度了,因为input是10以内,为了保证精度,可以*=10000。(不乘也可以,精度得开到14~16)
其他没啥说的。
注意上面的盘子需要和所有的盘子求交点,极角排序,判断该盘子的所有弧两端所属的那个盘子是否能看到(从最上面盘子往下扫,如果点在盘子上,说明能看到这个盘子)。

弧的中点我是用中垂线算出圆的两个交点,然后叉积判断下方向,舍掉一个点。

反正挺恶心的。。

模板增加个求弧中点的函数。。。



><崩溃,刚才搜题解,发现我做过这个题!!!POJ上的。。。方法不是太一样,http://blog.csdn.net/zxy_snow/article/details/6905911,哭了,两年前做的。。哎。老了。

#include <set>#include <map>#include <queue>#include <stack>#include <math.h>#include <stdio.h>#include <stdlib.h>#include <iostream>#include <limits.h>#include <string.h>#include <string>#include <algorithm>#define MID(x,y) ( ( x + y ) >> 1 )#define L(x) ( x << 1 )#define R(x) ( x << 1 | 1 )#define FOR(i,s,t) for(int i=(s); i<(t); i++)#define FORD(i,s,t) for(int i=(s-1); i>=t; i--)#define BUG puts("here!!!")#define STOP system("pause")#define file_r(x) freopen(x, "r", stdin)#define file_w(x) freopen(x, "w", stdout)using namespace std;const double eps = 1e-14;const int MAX = 110;const int BIG = 10000;struct point {double x, y;point (double x=0, double y=0):x(x), y(y) {}};int dcmp(double x) {return x < -eps ? -1 : x > eps ? 1 : 0;}double disp2p(point a,point b) //  a b 两点之间的距离 {return sqrt( ( a.x - b.x ) * ( a.x - b.x ) + ( a.y - b.y ) * ( a.y - b.y ) );}// 叉积 (三点)double crossProduct(point a,point b,point c)//向量 ac 在 ab 的方向 顺时针是正 {return (c.x - a.x)*(b.y - a.y) - (b.x - a.x)*(c.y - a.y);}struct circle {point c;double r;void big() {c.x *= BIG;c.y *= BIG;r *= BIG;}};bool c2c_inst(point a,double r1,point b,double r2){if( dcmp(disp2p(a,b) - (r1+r2)) < 0 && dcmp(disp2p(a,b) - fabs(r1 - r2)) > 0 )return true;return false;}circle c[MAX];point l2l_inst_p(point u1,point u2,point v1,point v2){point ans = u1;double t = ((u1.x - v1.x)*(v1.y - v2.y) - (u1.y - v1.y)*(v1.x - v2.x))/((u1.x - u2.x)*(v1.y - v2.y) - (u1.y - u2.y)*(v1.x - v2.x));ans.x += (u2.x - u1.x)*t;ans.y += (u2.y - u1.y)*t;return ans;}void l2c_inst_p(point c,double r,point l1,point l2,point &p1,point &p2){point p = c;double t;p.x += l1.y - l2.y;p.y += l2.x - l1.x;p = l2l_inst_p(p,c,l1,l2);t = sqrt(r*r - disp2p(p,c)*disp2p(p,c))/disp2p(l1,l2);p1.x = p.x + (l2.x - l1.x)*t;p1.y = p.y + (l2.y - l1.y)*t;p2.x = p.x - (l2.x - l1.x)*t;p2.y = p.y - (l2.y - l1.y)*t;}void c2c_inst_p(point c1,double r1,point c2,double r2,point &p1,point &p2){point u,v;double t;t = (1 + (r1*r1 - r2*r2)/disp2p(c1,c2)/disp2p(c1,c2))/2;u.x = c1.x + (c2.x - c1.x)*t;u.y = c1.y + (c2.y - c1.y)*t;v.x = u.x + c1.y - c2.y;v.y = u.y - c1.x + c2.x;l2c_inst_p(c1,r1,u,v,p1,p2);}int see[MAX];point ins[MAX], C;bool cmp(point a,point b)  {  double t1 = atan2(a.y - C.y, a.x - C.x);double t2 = atan2(b.y - C.y, b.x - C.x);    if( dcmp(t1 - t2) == 0 ) return dcmp(fabs(a.x) - fabs(b.x)) < 0 ? true : false;    return dcmp(t1 - t2) < 0 ? true : false;  }int l2c_inst_p(point c,double r,point l1,point l2,point *pv){int cnt = 0;double d = fabs( crossProduct(c,l1,l2) )/disp2p(l1,l2);if( dcmp(d-r) > 0 )return 0;point p = c;double t;p.x += l1.y - l2.y;p.y += l2.x - l1.x;p = l2l_inst_p(p,c,l1,l2);t = sqrt(r*r - disp2p(p,c)*disp2p(p,c))/disp2p(l1,l2);pv[cnt].x = p.x + (l2.x - l1.x)*t;pv[cnt++].y = p.y + (l2.y - l1.y)*t;if( dcmp(d-r) == 0 )return cnt;pv[cnt].x = p.x - (l2.x - l1.x)*t;pv[cnt++].y = p.y - (l2.y - l1.y)*t;return cnt;}//弧ab的中点 point mid_in_arc(point a, point b, point c, double r) {point mid((a.x + b.x)/2, (a.y + b.y)/2);point p[3];int cnt = l2c_inst_p(c, r, mid, c, p);FOR(i, 0, cnt)if( crossProduct(c, a, p[i]) * crossProduct(c, p[i], b) && dcmp(crossProduct(c, a, p[i])) <= 0 )return p[i];}int solve(int n) {int ans = 0;memset(see, 0, sizeof(see));FOR(i, 0, n) {bool inst = false;int cnt = 0;FOR(k, i+1, n) {double d = disp2p(c[i].c, c[k].c);//被其他在它上面的圆包含了 if( dcmp(c[k].r - d - c[i].r) >= 0 ) {inst = true;see[i] = -1;break;}if( c2c_inst(c[i].c, c[i].r, c[k].c, c[k].r) )inst = true;}//与在它上面的圆都没有相交或包含在比它之上的圆中 if( inst == false )see[i] = 1;FOR(k, 0, n) {if( k == i ) continue;if( !c2c_inst(c[i].c, c[i].r, c[k].c, c[k].r) )continue;point a, b;c2c_inst_p(c[i].c, c[i].r, c[k].c, c[k].r, a, b);ins[cnt++] = a;ins[cnt++] = b;}C = c[i].c;sort(ins, ins+cnt, cmp);FOR(k, 0, cnt) {point mid = mid_in_arc(ins[k], ins[(k+1)%cnt], c[i].c, c[i].r);double inf = 1e12;point delta((c[i].c.x - mid.x)/(c[i].r*inf), (c[i].c.y - mid.y)/(c[i].r*inf));point p(mid.x - delta.x, mid.y - delta.y);for(int j=n-1; j>=0; j--) {if( dcmp(disp2p(p, c[j].c) - c[j].r) < 0 ) {if( see[j] == 0 ) {see[j] = 1;}break;}}p.x = mid.x + delta.x;p.y = mid.y + delta.y;bool nosee = false;if( see[i] == 1 )continue;FOR(j, i+1, n) {if( dcmp(disp2p(p, c[j].c) - c[j].r) < 0 ) {nosee = true;break;}}if( !nosee )see[i] = 1;}}FOR(i, 0, n)ans += see[i] == 1 ? 1 : 0;return ans;}int main() {int n;while( ~scanf("%d", &n) && n ) {FOR(i, 0, n) {scanf("%lf%lf%lf", &c[i].c.x, &c[i].c.y, &c[i].r);c[i].big();}int ans = solve(n);printf("%d\n", ans);}return 0;}