poj1819

就像discuss里说的
分类讨论:开头的,中间的,结尾的。三类讨论一下就好了。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <set>
using namespace std;
const int MAXN = 1e3 + 5;
const double EPS = 1e-6;

struct Point
{
    Point() {}
    Point(double _x, double _y): x(_x), y(_y) {}

    double getDis(Point &rhs)
    {
        double xx = rhs.x - x, yy = rhs.y - y;
        return sqrt(xx * xx + yy * yy);
    }

    double x, y;
};

double operator ^(Point lhs, Point rhs){return lhs.x * rhs.y - lhs.y * rhs.x;}
Point operator -(Point lhs, Point rhs){return Point(rhs.x - lhs.x, rhs.y - lhs.y);}

struct Circle
{
    Circle() {}
    Circle(Point _o, double _r): o(_o), r(_r) {}

    double getDis(Circle &rhs)
    {
        return o.getDis(rhs.o);
    }

    Point o;
    double r;
};

Circle circle[MAXN];

int n;
set<int> dispense;

Circle getO(Circle &pre, double r)
{
    double difr = pre.r - r;
    double sumr = pre.r + r;
    double xx = sqrt(sumr * sumr - difr * difr);
    return Circle(Point(pre.o.x + xx, r), r);
}

void solve()
{
    circle[1].o = Point(circle[1].r, circle[1].r);
    double maxr = circle[1].o.x + circle[1].r;
    for(int i = 2; i <= n; ++i)
    {
        circle[i] = getO(circle[i - 1], circle[i].r);
        if(circle[i].o.x < circle[i].r)
        {
            circle[i].o.x = circle[i].r;
            for(int j = i - 1; j >= 1; --j)
            {
                dispense.insert(j);
            }
        }

        int depend = i - 1;
        for(int j = i - 2; j >= 1; --j)
        {
            Circle temp = getO(circle[j], circle[i].r);
            if(circle[j].getDis(circle[i]) < circle[j].getDis(temp) - EPS)
            {
                circle[i] = temp;
                depend = j;
            }
        }
        maxr = max(maxr, circle[i].o.x + circle[i].r);

        if(depend != i - 1)
        {
            for(int j = depend + 1; j < i; ++j)
            {
                dispense.insert(j);
            }
        }
    }
    for(int i = n; circle[i].o.x + circle[i].r < maxr; --i)
    {
        dispense.insert(i);
    }
}

int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i)
    {
        scanf("%lf", &circle[i].r);
    }
    solve();
    int l = dispense.size();
    printf("%d\n", l);
    set<int>::iterator p;
    for(p = dispense.begin(); p != dispense.end(); ++p)
    {
        printf("%d\n", *p);
    }
}