UVa 10969 (圆与圆之间的覆盖问题) Sweet Dream
2014-12-07 00:49
267 查看
题意:
有n个按先后顺序放置的不同大小不同位置的圆,求所有可见圆弧的长度。
分析:
这道题应该是大白书上例题 LA 2572 (求可见圆盘的数量) Kanazawa 的加强版,整体框架都差不多。
对于每个圆求出与其他圆相交的交点所对应的幅角(转化到[0, 2π]中),排个序,然后枚举每段弧的终点,如果不被后面放置的圆所覆盖则可见。
注意:
原本以为WA是精度问题,后来调大调小都一直WA,这里精度eps从1e-11到1e-13都没问题。
但是在判断弧的终点是否被圆所覆盖的时候要加上等号。也就是第64行代码中是<=而非<,一直被这个给坑惨了。
UVa的数据真的好强啊,Orz
代码君
有n个按先后顺序放置的不同大小不同位置的圆,求所有可见圆弧的长度。
分析:
这道题应该是大白书上例题 LA 2572 (求可见圆盘的数量) Kanazawa 的加强版,整体框架都差不多。
对于每个圆求出与其他圆相交的交点所对应的幅角(转化到[0, 2π]中),排个序,然后枚举每段弧的终点,如果不被后面放置的圆所覆盖则可见。
注意:
原本以为WA是精度问题,后来调大调小都一直WA,这里精度eps从1e-11到1e-13都没问题。
但是在判断弧的终点是否被圆所覆盖的时候要加上等号。也就是第64行代码中是<=而非<,一直被这个给坑惨了。
UVa的数据真的好强啊,Orz
#include <cstdio> #include <cmath> #include <vector> #include <algorithm> using namespace std; const int maxn = 100 + 10; const double eps = 1e-11; const double PI = acos(-1.0); const double TWO_PI = 2.0 * PI; double radius[maxn]; double NormalizeAngle(double ang) { return ang - TWO_PI*floor(ang/TWO_PI); } int dcmp(double x) { if(fabs(x) < eps) return 0; return x < 0 ? -1 : 1; } struct Point { double x, y; Point(double x=0, double y=0):x(x), y(y) {} }p[maxn]; typedef Point Vector; bool operator == (const Point& A, const Point& B) { return dcmp(A.x - B.x) == 0 && dcmp(A.y - B.y) == 0; } Point operator - (const Point& A, const Point& B) { return Point(A.x - B.x, A.y - B.y); } double Dot(const Point& A, const Point& B) { return A.x*B.x + A.y*B.y; } double Length(const Vector& A) { return sqrt(Dot(A, A)); } double Angle(const Vector& A) { return atan2(A.y, A.x); } void GetCCIntersection(const Point& c1, double r1, const Point& c2, double r2, vector<double>& rad) { double d = Length(c1 - c2); if(dcmp(d) == 0) return; if(dcmp(d-r1-r2) > 0) return; if(dcmp(d-fabs(r1-r2)) < 0) return; double base = Angle(c2 - c1); double ang = acos((r1*r1 + d*d - r2*r2) / (2.0*r1*d)); rad.push_back(NormalizeAngle(base + ang)); rad.push_back(NormalizeAngle(base - ang)); } int n; bool isVisible(const Point& C, int id) { for(int i = id + 1; i < n; ++i) { double d = Length(C - p[i]); if(dcmp(d - radius[i]) <= 0) return false; //这道题的关键所在 } return true; } int main(void) { //freopen("10969in.txt", "r", stdin); int T; scanf("%d", &T); while(T--) { scanf("%d", &n); for(int i = 0; i < n; ++i) scanf("%lf%lf%lf", &radius[i], &p[i].x, &p[i].y); double sum = 0.0; for(int i = 0; i < n; ++i) { vector<double> rad; rad.push_back(0.0); rad.push_back(TWO_PI); for(int j = 0; j < n; ++j) { if(j == i) continue; GetCCIntersection(p[i], radius[i], p[j], radius[j], rad); } sort(rad.begin(), rad.end()); for(int j = 0; j < rad.size() - 1; ++j) { double mid = (rad[j] + rad[j + 1]) / 2; double ang = rad[j + 1] - rad[j]; Point C(p[i].x + radius[i]*cos(mid), p[i].y + radius[i]*sin(mid)); if(isVisible(C, i)) sum += radius[i] * ang; } } printf("%.3f\n", sum); } return 0; }
代码君
相关文章推荐
- UVa 10969 Sweet Dream 继续圆盘问题
- UVA 10020 Minimal coverage(最小覆盖问题)
- UVA 10020 Minimal coverage(贪心 + 区间覆盖问题)
- [算法入门经典] 区间最少覆盖问题 UVA 10020 - Minimal coverage
- uva 10020 Minimal coverage(贪心-最小覆盖问题)
- 【区间覆盖问题】uva 10020 - Minimal coverage
- 网页上的DIV, IFRAME标签, ActiveX控件之间互相覆盖的问题
- 类之间的覆盖问题
- UVA10382- Watering Grass(区间覆盖问题)
- uva 10382 - Watering Grass(区域覆盖问题)
- UVA 10382 Watering Grass(变相的最小覆盖问题)
- UVA 10020 Minimal coverage 区间覆盖问题 贪心
- uvalive 2326 - Moving Tables(区间覆盖问题)
- UVA 10969 Sweet Dream(圆的相交)
- UVa 10382 - Watering Grass(贪心算法,区间覆盖问题)
- UVA 10020 Minimal coverage(贪心 + 区间覆盖问题)
- uvalive 2326 - Moving Tables(区间覆盖问题)
- UVA1292-----Strategic game-----树形DP解决树上的最小点覆盖问题
- UVa 10382 - Watering Grass(贪心+区间覆盖问题)
- uva 10969 - Sweet Dream(几何)