Google codejam 2010 Round 2 :: Grazing Google Goats

考试的时候只写了处理两个圆的,最后一刻写完的,交上去WA了。。后来才知道,要用long double

 

看了Google的题解,发现其方法确实很不错。Google提出了两种方法,都是O(n logn)的:

  1、通过inversion 变换,转化成半平面求交的问题。inversion变换我以前确实没听说过,开了眼界了。。

  2、由于所有圆过公共点,把圆心按极角排序后,用一个栈维护以Q为原点的极坐标系中,在某个极角区间内最近的圆是哪个。

 

我实现了方法2,程序并不长,但写的时候感到有些纠结,幸好一次AC,要不还没法调……

 

/* * $File: d.cpp * $Date: Sun Jun 06 17:10:33 2010 +0800 */ #include <cstdio> #include <cmath> #include <algorithm> using namespace std; namespace Solve { const int NPOINT_MAX = 5005; typedef long double Real_t; struct Point { int x, y; inline int mod()const {return x * x + y * y;} }; struct Vector { int x, y; inline Real_t len() const {return sqrt((Real_t)(x * x + y * y));} inline int operator * (const Vector &v) const {return x * v.y - v.x * y;} inline int dot(const Vector &v) const {return x * v.x + y * v.y;} Vector(const Point &p1, const Point &p2) : x(p2.x - p1.x), y(p2.y - p1.y) {} Vector(const Point &p) : x(p.x), y(p.y) {} Vector() : x(0), y(0) {} }; Vector rotate_clockwise(const Vector &v); Vector rotate_counterclocksise(const Vector &v); Point point[NPOINT_MAX]; int npoint; inline bool point_cmt_angle(const Point &p1, const Point &p2) {return Vector(p1) * p2 > 0;} Real_t work(); Real_t calc_area(const Point &p0, const Vector &d1, const Vector &d2); Real_t calc_angle(const Vector &v1, const Vector &v2); void solve(FILE *fin, FILE *fout); } void Solve::solve(FILE *fin, FILE *fout) { int ncase; fscanf(fin, "%d", &ncase); for (int id = 1; id <= ncase; id ++) { int n, m; static Point p0[NPOINT_MAX]; fscanf(fin, "%d%d", &n, &m); for (int i = 0; i < n; i ++) fscanf(fin, "%d%d", &p0[i].x, &p0[i].y); fprintf(fout, "Case #%d:", id); for (int i = 0; i < m; i ++) { int x0, y0; fscanf(fin, "%d%d", &x0, &y0); npoint = n; for (int j = 0; j < n; j ++) point[j].x = p0[j].x - x0, point[j].y = p0[j].y - y0; fprintf(fout, " %.9Lf", work()); } fprintf(fout, "/n"); } } Solve::Real_t Solve::work() { struct Stack_node { Vector dir; int p; // p is the point before dir }; static Stack_node stack[NPOINT_MAX]; // stack is in the clockwise order! sort(point, point + npoint, point_cmt_angle); int n = 0; for (int i = 0; i < npoint; ) { point[n] = point[i]; i ++; while (i < npoint && Vector(point[i]) * point[i - 1] == 0) { if (Vector(point[i]).dot(point[n]) < 0) return 0; if (point[i].mod() < point[n].mod()) point[n] = point[i]; i ++; } n ++; } int nstack = 2; stack[1].p = 0; stack[0].dir = rotate_counterclocksise(point[0]); stack[1].dir = rotate_clockwise(point[0]); for (int i = 1; i < n; i ++) { Vector vs = rotate_clockwise(point[i]), vt = rotate_counterclocksise(point[i]); if (vs * stack[0].dir <= 0 && vt * stack[nstack - 1].dir >= 0) return 0; while (nstack >= 2) { Vector tmp = rotate_clockwise(Vector(point[stack[nstack - 1].p], point[i])); if (tmp * stack[nstack - 1].dir >= 0) break; if (tmp * stack[nstack - 2].dir >= 0) { stack[nstack - 1].dir = tmp; stack[nstack].dir = vs; stack[nstack].p = i; nstack ++; break; } nstack --; } if (nstack < 2) return 0; } Real_t ans = 0; for (int i = 1; i < nstack; i ++) ans += calc_area(point[stack[i].p], stack[i].dir, stack[i - 1].dir); return ans; } Solve::Real_t Solve::calc_area(const Point &p0, const Vector &d1, const Vector &d2) { Real_t a = calc_angle(rotate_clockwise(p0), d1), b = calc_angle(d1, d2); return p0.mod() * (b * 2 + sin(a * 2) - sin(2 * (a + b))) / 2; } Solve::Vector Solve::rotate_clockwise(const Vector &v) { Vector ans; ans.x = v.y; ans.y = -v.x; return ans; } Solve::Vector Solve::rotate_counterclocksise(const Vector &v) { Vector ans; ans.x = -v.y; ans.y = v.x; return ans; } Solve::Real_t Solve::calc_angle(const Vector &v1, const Vector &v2) { Real_t tmp = v1.dot(v2) / v1.len() / v2.len(); if (tmp > 1) tmp = 1; if (tmp < -1) tmp = -1; // deal with error. return acos(tmp); } int main() { Solve::solve(stdin, stdout); }

 

顺便说一下比赛经过:

  最开始把第一题理解错了,想了半天觉得不可做,然后把第二题写了,把第三题小点裸了,这时候还有一个多小时。。 想了很久第四题,觉得一个小时肯定实现不了,仔细一看,小点只有两个圆。。 很高兴,但写的时候纠结了…… 最后不到5分钟时写完,过了样例,还没交,先看了下排名,大概四百八九。。 然后我想赌一把,结果不幸WA掉了,排名瞬间跌至506。。 然后不敢动了,过了几秒比赛结束,刷新一下,最后排名460,幸亏前面有人WA了大点……

 

你可能感兴趣的:(Date,struct,vector,File,Google,2010)