题目链接:https://vjudge.net/problem/POJ-1819

题意:给你一些圆,问你水平排序后可以删除哪些圆不影响。

我们可以这样,从左往右枚举 c[i] 圆,然后从小于 i 的 园中找与其相切的相对应横坐标x,取个max,然后就得到坐标,两坐标间的圆可删去。注意特判最左和最右。

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 using namespace std;
 5 const int N = 1e3+9;
 6 struct Circle{
 7     double x,y,r;
 8 }p[N];
 9 int vis[N];
10 double cir_cir(Circle c,double lr){
11     double d = sqrt( (c.r+lr)*(c.r+lr) - (c.r-lr)*(c.r-lr));
12     return c.x + d;
13 }
14 int main(){
15     int n; scanf("%d",&n);
16     for(int i = 1; i <= n;++i) scanf("%lf",&p[i].r);
17     p[1].x = p[1].y = p[1].r;
18     for(int i = 2;i<=n;++i){
19         double maxx = -1;
20         int le;
21         for(int j = i-1 ; j>=1;--j){
22             double temx = cir_cir(p[j],p[i].r);
23             if(temx > maxx){
24                 maxx = temx;
25                 le = j;
26             }
27         }
28         p[i].x = maxx; p[i].y = p[i].r;
29         for(int u = i-1;u>le;--u) vis[u] = 1;
30     }
31     for(int i = 2;i<=n;++i){
32         if(p[i].x <= p[i].r ){
33             for(int j = 1;j<i;++j) vis[j] = 1;
34         }
35     }
36     double ri = p[n].x + p[n].r;
37     for(int i = 1;i<n;++i){
38         if( ri - p[i].x <= p[i].r ){
39             for(int j = i+1;j<=n;++j) vis[j] = 1;
40         }
41     }
42     int tot = 0;
43     for(int i = 1;i<=n;++i){
44         // cerr<<i<<' '<<vis[i]<<endl;
45         tot+=vis[i];
46     }
47     printf("%d\n",tot);
48     for(int i = 1;i<=n;++i) if(vis[i]) printf("%d\n",i);
49     return 0;
50 }
View Code
02-10 23:09