可知最终结果一定经过一个上边缘的点和一个下边缘的点,否则可以平移直线使结果更优。
所以枚举所有上边缘点和下边缘点的点对,计算最大交点,或者通过整个管道。
#include <iostream>
#include <cmath>
#include <algorithm>
#include <iomanip>
using namespace std;
const double eps = 1e-9;
const int INF = 0x3f3f3f3f;
const int MAXN = 25;
struct Point //点
{
double x;
double y;
}up[MAXN], down[MAXN]; //上边缘点,下边缘点
int n;
//判断x是正数、负数、零
int judge(double x)
{
return fabs(x) < eps ? 0 : (x > 0 ? 1 : -1);
}
//计算两个向量的叉积
double cross(Point& a, Point& b, Point& c)
{
return (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y);
}
//判断两条直线是否相交
bool isIntersect(Point& a, Point& b, Point& c, Point& d)
{
return judge(cross(a, b, c)) * judge(cross(a, b, d)) <= 0;
}
//计算两条直线交点的横坐标
double getX(Point& a, Point& b, Point& c, Point& d)
{
double s1 = cross(a, b, c);
double s2 = cross(a, b, d);
int d1 = judge(s1);
int d2 = judge(s2);
if (d1 * d2 != 0)
return (s2 * c.x - s1 * d.x) / (s2 - s1);
else if (d1 == 0)
return c.x;
else if (d2 == 0)
return d.x;
else
return -INF;
}
void solve()
{
double ans = -INF;
//枚举所有上边缘点和下边缘点的点对
for (int i = 0; i < n; i++) //上边缘点
{
for (int j = 0; j < n; j++) //下边缘点
{
if (i == j)
continue;
int k;
for (k = 0; k < n; k++)
{
if (!isIntersect(up[i], down[j], up[k], down[k]))
break;
}
if (k == n) //光线通过整个管道
{
cout << "Through all the pipe." << endl;
return;
}
if (k > max(i, j))
{
ans = max(getX(up[i], down[j], up[k], up[k - 1]), ans);
ans = max(getX(up[i], down[j], down[k], down[k - 1]), ans);
}
}
}
cout << fixed << setprecision(2) << ans << endl;
}
int main()
{
while (cin >> n)
{
if (n == 0)
break;
for (int i = 0; i < n; i++)
{
cin >> up[i].x >> up[i].y;
down[i].x = up[i].x;
down[i].y = up[i].y - 1;
}
solve();
}
return 0;
}
继续加油。