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);
}
}