pku 1039 Pipe 叉积的应用
http://poj.org/problem?id=1039
黑书上的一道题目:
题意:有一宽度为1的折线管道,上面顶点为(xi,yi),所对应的下面顶点为(xi,yi-1),假设管道都是不透明的,不反射的,光线从左边入口处的(x0,y0),(x,y0-1)之间射入,向四面八方传播,求解光线最远能传播到哪里(取x坐标)或者是否能穿透整个管道.
如果一根光线自始至终都未擦到任何顶点,那么它肯定不是最优的,因为可以通过平移来使之优化,如果只碰到一个顶点,那也不是最优的,可以通过旋转,使它碰到另一个顶点,并且更优,即最优光线一定擦到一个上顶点和一个下顶点.
这样枚举所有的上下两个转折点形成线段,然后从0到n枚举所有转折点如果与之相交则满足,直到找到不想交的然后计算x,找出最大的x即可。
#include <cstdio>
#include <cstring>
#include <iostream>
#define maxn 21
using namespace std;
const double eps = 1e-8;
struct point
{
double x,y;
}up[maxn],down[maxn];
int n;
int dblcmp(double x)
{
if (x > eps) return 1;
else if (x < -eps) return -1;
else return 0;
}
double det(double x1,double y1,double x2,double y2)
{
return x1*y2 - x2*y1;
}
double cross(point a,point b,point c)
{
return det(b.x - a.x,b.y - a.y,c.x - a.x,c.y - a.y);
}
double getx(point a,point b,point c,point d)
{
double k1,k2,b1,b2;
k1 = (b.y - a.y)/(b.x - a.x);
k2 = (d.y - c.y)/(d.x - c.x);
b1 = a.y - k1*a.x;
b2 = d.y - k2*d.x;
return (b2 - b1)/(k1 - k2);
}
void solve()
{
int i,j,k;
double ans = -10000000.0;
for (i = 0; i < n; ++i)
{
for (j = 0; j < n; ++j)
{
if (i == j) continue;//同一个转折点上下就不用了
//寻找不想交的
for (k = 0; k < n; ++k)
{
if (dblcmp(cross(up[i],down[j],up[k]))*dblcmp(cross(up[i],down[j],down[k])) > 0)
break;
}
double temp = 0;
//计算x,并求出最大
if (k < max(i,j)) continue;
temp = getx(up[i],down[j],up[k],up[k - 1]);
if (temp > ans) ans = temp;
temp = getx(up[i],down[j],down[k],down[k - 1]);
if (temp > ans) ans = temp;
if (k >= n)
{
printf("Through all the pipe.\n");
return ;
}
}
}
printf("%.2lf\n",ans);
}
int main()
{
int i;
while (~scanf("%d",&n))
{
if (!n) break;
for (i = 0; i < n; ++i)
{
scanf("%lf%lf",&up[i].x,&up[i].y);
down[i].x = up[i].x;
down[i].y = up[i].y - 1.0;
}
solve();
}
return 0;
}


浙公网安备 33010602011771号