LA 2572 Kanazawa

题意:

把n个圆盘依次放到桌面上,按照放置的先后顺序给出这n个圆盘的圆心和半径,输出有多少个圆盘可见(即未被全部覆盖)。

分析:

题中说对输入数据进行微小扰动后答案不变。

所露出的部分都是由若干小圆弧组成的。因此求出每个圆与其他圆相交的小圆弧,取圆弧的终点,分别向里和向外移动一个很小的距离的到P‘。标记包含P‘的最上面的那个圆为可见。

  1 //#define LOCAL
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <cmath>
  6 #include <vector>
  7 using namespace std;
  8
  9 const int maxn = 110;
 10 const double PI = acos(-1.0);
 11 const double Two_PI = PI * 2;
 12 const double eps = 5 * 1e-13;
 13 int n;
 14 double radius[maxn];
 15 bool vis[maxn];
 16
 17 int dcmp(double x)
 18 {
 19     if(fabs(x) < eps)    return 0;
 20     else return x < 0 ? -1 : 1;
 21 }
 22
 23 struct Point
 24 {
 25     double x, y;
 26     Point(double x=0, double y=0):x(x), y(y) {}
 27 };
 28 typedef Point Vector;
 29 Point operator + (Point A, Point B)    { return Point(A.x+B.x, A.y+B.y); }
 30 Point operator - (Point A, Point B)    { return Point(A.x-B.x, A.y-B.y); }
 31 Vector operator * (Vector A, double p){ return Vector(A.x*p, A.y*p); }
 32 Vector operator / (Vector A, double p){ return Vector(A.x/p, A.y/p); }
 33 Point center[maxn];
 34
 35 double Dot(Vector A, Vector B){ return A.x*B.x + A.y*B.y; }
 36 double Length(Vector A){ return sqrt(Dot(A, A)); }
 37 double angle(Vector v)    { return atan2(v.y, v.x); }
 38 double NormalizeAngle(double rad)
 39 {//将所求角度化到0到2π之间
 40     return rad - Two_PI*(floor(rad/Two_PI));
 41 }
 42
 43 void getCCIntersection(Point c1, double r1, Point c2, double r2, vector<double>& rad)
 44 {
 45     double d = Length(c1 - c2);
 46     if(dcmp(d) == 0)    return;
 47     if(dcmp(d-r1-r2) > 0)    return;
 48     if(dcmp(d-fabs(r1-r2)) < 0)    return;
 49
 50     double a = angle(c2-c1);
 51     double ag = acos((r1*r1+d*d-r2*r2)/(2*r1*d));
 52     rad.push_back(NormalizeAngle(a + ag));
 53     rad.push_back(NormalizeAngle(a - ag));
 54 }
 55
 56 int topmost(Point P)
 57 {
 58     for(int i = n-1; i >= 0; --i)
 59         if(Length(P-center[i]) < radius[i])    return i;
 60     return -1;
 61 }
 62
 63 int main(void)
 64 {
 65     #ifdef LOCAL
 66         freopen("2572in.txt", "r", stdin);
 67     #endif
 68
 69     while(scanf("%d", &n) == 1 && n)
 70     {
 71         for(int i = 0; i < n; ++i)
 72             scanf("%lf%lf%lf", &center[i].x, &center[i].y, &radius[i]);
 73         memset(vis, 0, sizeof(vis));
 74
 75         for(int i = 0; i < n; ++i)
 76         {
 77             vector<double> rad;
 78             rad.push_back(0.0);
 79             rad.push_back(Two_PI);
 80             for(int j = 0; j < n && j != i; ++j)
 81                 getCCIntersection(center[i], radius[i], center[j], radius[j], rad);
 82             sort(rad.begin(), rad.end());
 83
 84             for(int j = 0; j < rad.size(); ++j)
 85             {
 86                 double mid = (rad[j] + rad[j+1]) / 2.0;
 87                 for(int side = -1; side <= 1; side += 2)
 88                 {
 89                     double r = radius[i] + side*eps;
 90                     int t = topmost(Point(center[i].x+r*cos(mid), center[i].y+r*sin(mid)));
 91                     if(t >= 0)    vis[t] = true;
 92                 }
 93             }
 94         }
 95         int ans = 0;
 96         for(int i = 0; i < n; ++i)    if(vis[i])    ++ans;
 97         printf("%d\n", ans);
 98     }
 99
100     return 0;
101 }

代码君

时间: 2024-10-26 08:52:29

LA 2572 Kanazawa的相关文章

UVa 10969 (圆与圆之间的覆盖问题) Sweet Dream

题意: 有n个按先后顺序放置的不同大小不同位置的圆,求所有可见圆弧的长度. 分析: 这道题应该是大白书上例题 LA 2572 (求可见圆盘的数量) Kanazawa 的加强版,整体框架都差不多. 对于每个圆求出与其他圆相交的交点所对应的幅角(转化到[0, 2π]中),排个序,然后枚举每段弧的终点,如果不被后面放置的圆所覆盖则可见. 注意: 原本以为WA是精度问题,后来调大调小都一直WA,这里精度eps从1e-11到1e-13都没问题. 但是在判断弧的终点是否被圆所覆盖的时候要加上等号.也就是第6

hdu 5745 la vie en rose

这道题的官方题解是dp,但是可以暴力出来.改天再研究怎么dp. 暴力的时候,如果计算sum的时候,调用strlen函数会超时,可见这个函数并不是十分的好.以后能不用尽量不用. La Vie en rose Time Limit: 14000/7000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 861    Accepted Submission(s): 461 Problem

让MAC OS也能使用LL LA L等LS的别名

linux下默认ll是ls -l的别名.OS X下默认不支持.习惯了linux下使用ll,我们同样也可以将习惯搬到os x下的shell中. 再当前用户家目录下新建.bash_profile文件.根据你的习惯,添加下面格式内容即可. 1 2 3 alias ll='ls -l' alias la='ls -a' alias l='ls -la' 然后执行:source .bash_profile你还可以添加你喜欢的其他别名.

LA 3942 Remember the Word (Trie)

Remember the Word 题目:链接 题意:给出一个有S个不同单词组成的字典和一个长字符串.把这个字符串分解成若干个单词的连接(单词可以重复使用),有多少种方法? 思路:令d[i]表示从字符i开始的字符串(后缀s[i..L])的分解数,这d[i] = sum{d(i+len(x)) | 单词x是其前缀}.然后将所有单词建成一个Trie树,就可以将搜索单词的复杂度降低. 代码: #include<map> #include<set> #include<queue>

LA 2678 Subsequence

有一个正整数序列,求最短的子序列使得其和大于等于S,并输出最短的长度. 用数组b[i]存放序列的前i项和,所以b[i]是递增的. 遍历终点j,然后在区间[0, j)里二分查找满足b[j]-b[i]≥S的最大的i,时间复杂度为O(nlongn). 这里二分查找用到库函数lower_bound() 1 //#define LOCAL 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 #inclu

LA 4127 - The Sky is the Limit (离散化 扫描线 几何模板)

题目链接 非原创 原创地址:http://blog.csdn.net/jingqi814/article/details/26117241 题意:输入n座山的信息(山的横坐标,高度,山底宽度),计算他们的轮廓线, 即露出来的表面边长,有些山是重叠的不计.空白地带不计,每座山都是等腰三角形. 分析:大白书P414页. 求小山的总长度,用一些虚线将其离散化,分成一段一段的,特征点:山脚,山顶,交点.这样就能保 证相邻两个扫描点之间再无交点.然后一最上面的点就是分割点,维护上一个点lastp即可. 1

LA 2031

Mr. White, a fat man, now is crazy about a game named ``Dance, Dance, Revolution". But his dance skill is so poor that he could not dance a dance, even if he dances arduously every time. Does ``DDR" just mean him a perfect method to squander his

Mac下ll、l、la、等简写命令不能使用

Mac默认用的也是Unix系统,Unix系统本身是没有这些简写命令的,可以通过给命令设置别名来使得可以使用这些简写命令 查看本机所有已经设置的命令别名:alias 设置命令别名:alias ll='ls -alF' 执行命令只在当前shell有效,要长期有效可以设置在用户的.bash_profile里面,这样每次登陆就都可以用这些简写命令了. 步骤: 1.vim ~/.bash_profile 2.将以下内容写入文件并保存 alias ll='ls -alF' alias la='ls -A'

Linux中.a,.la,.o,.so文件的意义和编程实现

Linux中.a,.la,.o,.so文件的意义和编程实现    Linux下文件的类型是不依赖于其后缀名的,但一般来讲:        .o,是目标文件,相当于windows中的.obj文件        .so 为共享库,是shared object,用于动态连接的,和dll差不多        .a为静态库,是好多个.o合在一起,用于静态连接        .la为libtool自动生成的一些共享库,vi编辑查看,主要记录了一些配置信息.可以用如下命令查看*.la文件的格式   $file