圆+细节——poj1819

/*
枚举前面的圆,找到最远的相切位置即可 
开头结尾的两种情况也不能忽略 
*/
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define N 2005
typedef double db;
const db eps=1e-6;
const db pi=acos(-1);
int sign(db k){if (k>eps) return 1; else if (k<-eps) return -1; return 0;}
int cmp(db k1,db k2){return sign(k1-k2);}
struct point{
    db x,y;
    point operator + (const point &k1) const{return (point){k1.x+x,k1.y+y};}
    point operator - (const point &k1) const{return (point){x-k1.x,y-k1.y};}
    point operator * (db k1) const{return (point){x*k1,y*k1};}
    point operator / (db k1) const{return (point){x/k1,y/k1};}
    db abs(){return sqrt(x*x+y*y);}
    db dis(point k1){return ((*this)-k1).abs();}
};

struct circle{
    point o;
    db r;
};
circle c[N];

int n,flag[N];


int main(){
    while(cin>>n){
    for(int i=1;i<=n;i++)cin>>c[i].r;
    
    c[1].o.x=c[1].o.y=c[1].r;
    for(int i=2;i<=n;i++){
        db mx=0,id;
        for(int j=i-1;j>=1;j--){
            db a=fabs(c[i].r-c[j].r);
            db b=c[i].r+c[j].r;
            db dis=sqrt(b*b-a*a);
            db x=dis+c[j].o.x;
            if(sign(x-mx)>=0)mx=x,id=j;
        }
        c[i].o.x=mx;
        c[i].o.y=c[i].r;
        if(sign(mx-c[i].r)<=0){//把所有前面的都覆盖了 
            for(int j=1;j<i;j++)flag[j]=1; 
            continue;
        } 
        for(int j=id+1;j<i;j++)
            flag[j]=1;
    }
    
    db mx=0;
    for(int i=1;i<=n;i++)
        mx=max(mx,c[i].r+c[i].o.x);
    
    //把所有后面的都覆盖了 
    int i=1;
    for(;i<=n;i++){
        if(sign(c[i].o.x+c[i].r-mx)>=0)
            break;
    }
    for(int j=i+1;j<=n;j++)
        flag[j]=1;
    
    
    int K=0;
    for(int i=1;i<=n;i++)
        K+=flag[i];
    cout<<K<<'\n';
    for(int i=1;i<=n;i++)
        if(flag[i])cout<<i<<'\n';
    }
}
 

猜你喜欢

转载自www.cnblogs.com/zsben991126/p/12349648.html