比较巧妙的物理几何题,参考自大神的解题报告,题意就是给一些不重复的圆,然后把一根棍子放到这些圆上,判断会不会掉下来,在物理上来说就是重心(即线段中心)两端都要有点在圆上,这样才能保证不掉下来,思路就是把线段均分,依次枚举所有切分点,判断这些点是否在圆上,然后看看最外侧的两个在圆上的点是否在重心两侧
#include<cstdio>
#include<vector>
using namespace std;
namespace
{
const int D = 500;
const double eps = 1e-8;
struct Circle
{
double x, y, r;
};
int sgn(double a)
{
return a < -eps ? -1 : a < eps ? 0 : 1;
}
bool in_circle(double x, double y, vector<Circle *> &V)
{
for (size_t i = 0; i < V.size(); i++)
{
double dis = (x - V[i]->x) * (x - V[i]->x)
+ (y - V[i]->y) * (y - V[i]->y) - (V[i]->r) * (V[i]->r);
if (sgn(dis) <= 0)
return true;
}
return false;
}
}
int main()
{
int N;
vector<Circle *> V;
vector<pair<double, double> > U;
double x, y, bx, by, ex, ey;
while (scanf("%d", &N), N)
{
V.clear();
U.clear();
while (N--)
{
Circle *c = new Circle();
scanf("%lf %lf %lf", &(c->x), &(c->y), &(c->r));
V.push_back(c);
}
scanf("%lf %lf %lf %lf", &bx, &by, &ex, &ey);
double sx = (ex - bx) / D, sy = (ey - by) / D;
if (in_circle(bx, by, V))
U.push_back(make_pair(bx, by));
for (int i = 1; i < D; i++)
{
x = bx + i * sx;
y = by + i * sy;
if (in_circle(x, y, V))
U.push_back(make_pair(x, y));
}
if (in_circle(ex, ey, V))
U.push_back(make_pair(ex, ey));
if (U.size() >= 2)
{
double mx = (bx + ex) / 2, my = (by + ey) / 2;
double fx = U.front().first, fy = U.front().second;
double lx = U.back().first, ly = U.back().second;
if ((fx - mx) * (lx - mx) + (fy - my) * (ly - my) < 0)
puts("STAY");
else
puts("FALL");
}
else
puts("FALL");
for (size_t i = 0; i < V.size(); i++)
delete V[i];
}
return 0;
}