【kuangbin专题】计算几何基础(综合)


【POJ 1039】Pipe

【题目描述】 有个管子,有 n 个转折点,管子宽度为 1 ,问有没有一条直线能够穿过这个管子,如果不能,问最远能够到达哪里,输出照到的点的横坐标

【题目思路】我们可以想到,这个光线能够穿过管子的极限情况是,擦着一个下底面点和一个上顶面点,所以我们只需要枚举下面的点和上面的点连成的直线,判断其是否能够穿过所有管子

注意:

1.判断光线是否穿过管子当前的转折点,可以判断这条直线是不是和这个管子那个转折点的上下点组成的线段相切

2.最开始没有想明白,就直接枚举,以后要想清楚

  1 #include<cstdio>
  2 #include<algorithm>
  3 #define ll double 
  4 using namespace std;
  5 const int    MAXN = 510;
  6 const double eps  = 1e-3;
  7 struct P
  8 {
  9     ll x, y;
 10     P(ll a=0,ll b=0):x(a),y(b){}
 11     P  operator-(P a) { return P(x - a.x, y - a.y); }
 12     P  operator+(P a) { return P(x + a.x, y + a.y); }
 13     ll operator^(P a) { return a.y*x - a.x*y; }
 14     ll operator*(P a) { return a.x*x + a.y*y; }
 15 }up[MAXN],down[MAXN];
 16 struct L
 17 {
 18     P s, t;
 19     L() {};
 20     L(P a, P b) :s(a), t(b) {}
 21 }up_L[MAXN],down_L[MAXN];
 22 int sgn(double x)
 23 {
 24     if (x > eps)    return 1;
 25     if (x < -eps) return -1;
 26     return 0;
 27 }
 28 ll cross(P a, P b)
 29 {
 30     return a ^ b;
 31 }
 32 ll cross(P a, P b, P c)
 33 {
 34     return (a - c) ^ (b - c);
 35 }
 36 int L_is_inter(L a, L b)
 37 {
 38     return sgn(cross(b.s, a.s, a.t))*sgn(cross(b.t, a.s, a.t));
 39 }
 40 bool S_is_inter(L a, L b)
 41 {
 42     return sgn((a.s - a.t) ^ (b.s - b.t)) == 0;
 43 }
 44 P get_inter(L a, L b)
 45 {
 46     return a.s + (a.t - a.s)*(cross(b.t - b.s, a.s - b.s)) / cross(a.t - a.s, b.t - b.s);
 47 }
 48 int main()
 49 {
 50     int n=1;
 51     while (1)
 52     {   
 53         scanf("%d", &n);if (n==0)    break;
 54         for (int i = 1; i <= n; i++)
 55         {
 56             double x, y;
 57             scanf("%lf %lf ", &x, &y);
 58             up[i]   = P(x, y);
 59             down[i] = P(x, y - 1);
 60             if (i == 1) continue;
 61             up_L[i]   = L(up[i - 1], up[i]);
 62             down_L[i] = L(down[i - 1], down[i]);
 63         }
 64         ll   ans  = -10000000000.0;
 65         P tmp;
 66         bool flag = 0;
 67         for (int i = 1; i <= n; i++)
 68         {
 69             for (int j = 1; j <= n; j++)
 70             {
 71                 if (i == j)    continue;
 72                 L t = L(down[i], up[j]);
 73                 int k;
 74                 for ( k = 1; k <= n; k++)
 75                 {
 76                     L    line = L(down[k], up[k]);
 77                     bool ret = (L_is_inter(t, line)<=0);
 78                     if (k == 1)
 79                     {
 80                         if (ret)
 81                             continue;
 82                         else
 83                         {
 84                             break;
 85                         }
 86                     }
 87                     if (!ret)
 88                     {
 89                         line = L(up[k - 1], up[k]);
 90                         if (L_is_inter(t, line)<0)
 91                         {
 92                             tmp = get_inter(t, line);
 93                             //printf("i==%d  j==%d k=%d tmp==%lf\n", i, j, k, tmp.x);
 94                             ans = max(ans, tmp.x);
 95                         }
 96                         line = L(down[k - 1], down[k]);
 97                         if (L_is_inter(t, line)<0)
 98                         {
 99 
100                             tmp = get_inter(t, line);
101                             //printf("i==%d  j==%d k=%d tmp==%lf\n", i, j, k, tmp.x);
102                             ans = max(ans, tmp.x);
103                         }
104                         break;
105                     }
106                 }
107                 if (k > n) { flag = 1; break; }
108             }
109                 if (flag)    break;
110         }
111         if (flag) { printf("Through all the pipe.\n"); }
112         else
113         printf("%.2f\n", ans);
114     }
115     return 0;
116 }
View Code

猜你喜欢

转载自www.cnblogs.com/rentu/p/11649309.html
今日推荐