POJ 1039 (求线段交点 + 思维)

题目:传送门

题意:有一个 n 个拐点的曲折的管道,你有一束光射进去(直射),问你最远能射到点的 x 坐标是多大。

      1 <= n <= 20

思路:首先需要想到,这条线肯定是经过管道的一个上拐点和一个下拐点。

   然后就枚举所有情况就行了。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#include <map>
#include <vector>
#include <set>
#include <string>
#include <math.h>
#define LL long long
#define mem(i, j) memset(i, j, sizeof(i))
#define rep(i, j, k) for(int i = j; i <= k; i++)
#define dep(i, j, k) for(int i = k; i >= j; i--)
#define pb push_back
#define make make_pair
#define INF INT_MAX
#define inf LLONG_MAX
#define PI acos(-1)
using namespace std;

const int N = 1e2 + 5;
const double eps = 1e-10;

struct Point {
    double x, y;
    Point(double x = 0, double y = 0) : x(x), y(y) { }
};

int dcmp(double x) {
    if(fabs(x) < eps) return 0; else return x < 0 ? -1 : 1;
}

Point operator + (Point A, Point B) { return Point(A.x + B.x, A.y + B.y); }
Point operator - (Point A, Point B) { return Point(A.x - B.x, A.y - B.y); }
Point operator * (Point A, double p) { return Point(A.x * p, A.y * p); }
Point operator / (Point A, double p) { return Point(A.x / p, A.y / p); }

double Cross(Point A, Point B) { return A.x * B.y - A.y * B.x; }
double Dot(Point A, Point B) { return A.x * B.x + A.y * B.y; }

inline Point GLI(Point P, Point v, Point Q, Point w) {///求直线p + v*t 和 Q + w*t 的交点,需确保有交点,v和w是方向向量
    Point u = P - Q;
    double t = Cross(w, u) / Cross(v, w);
    return P + v * t;
}

inline bool LSPI(Point b1, Point b2, Point a1, Point a2) { /// 判断直线b1b2是否与线段a1a3相交
    return dcmp(Cross(b1 - a1, b2 - a1)) * dcmp(Cross(b1 - a2, b2 - a2)) <= 0;
}

Point up[N], dw[N];

int main() {

    int n;
    while(scanf("%d", &n) && n) {
        rep(i, 1, n) {
            scanf("%lf %lf", &up[i].x, &up[i].y);
            dw[i].x = up[i].x;
            dw[i].y = up[i].y - 1;
        }
        bool flag = 0;
        double ans = -100000000.0;
        rep(i, 1, n) rep(j, i + 1, n) {
            int pos;
            for(pos = 1; pos <= n; pos++) if(LSPI(up[i], dw[j], up[pos], dw[pos]) == false) break;
            if(pos > n) { flag = 1; break; }
            if(pos > j) {
                if(LSPI(up[i], dw[j], up[pos], up[pos - 1])) {
                    Point tmp = GLI(up[i], dw[j] - up[i], up[pos], up[pos - 1] - up[pos]);
                    ans = max(ans, tmp.x);
                }
                if(LSPI(up[i], dw[j], dw[pos], dw[pos - 1])) {
                    Point tmp = GLI(up[i], dw[j] - up[i], dw[pos], dw[pos - 1] - dw[pos]);
                    ans = max(ans, tmp.x);
                }
            }

            for(pos = 1; pos <= n; pos++) if(LSPI(dw[i], up[j], up[pos], dw[pos]) == false) break;
            if(pos > n) { flag = 1; break; }
            if(pos > j) {
                if(LSPI(dw[i], up[j], up[pos], up[pos - 1])) {
                    Point tmp = GLI(dw[i], up[j] - dw[i], up[pos], up[pos - 1] - up[pos]);
                    ans = max(ans, tmp.x);
                }
                if(LSPI(dw[i], up[j], dw[pos], dw[pos - 1])) {
                    Point tmp = GLI(dw[i], up[j] - dw[i], dw[pos], dw[pos - 1] - dw[pos]);
                    ans = max(ans, tmp.x);
                }
            }
            if(flag) break;
        }
        if(flag) puts("Through all the pipe.");
        else printf("%.2f\n", ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Willems/p/12392085.html

时间: 2024-10-10 09:13:36

POJ 1039 (求线段交点 + 思维)的相关文章

谈谈&quot;求线段交点&quot;的几种算法(js实现,完整版)

"求线段交点"是一种非常基础的几何计算, 在很多游戏中都会被使用到. 下面我就现学现卖的把最近才学会的一些"求线段交点"的算法总结一下, 希望对大家有所帮助. 本文讲的内容都很初级, 主要是面向和我一样的初学者, 所以请各位算法帝们轻拍啊 嘎嘎 引用 已知线段1(a,b) 和线段2(c,d) ,其中a b c d为端点, 求线段交点p .(平行或共线视作不相交) =============================== 算法一: 求两条线段所在直线的交点, 再

求线段交点&quot;的几种算法(js实现,完整版)

"求线段交点"是一种非常基础的几何计算, 在很多游戏中都会被使用到. 下面我就现学现卖的把最近才学会的一些"求线段交点"的算法说一说, 希望对大家有所帮助. 本文讲的内容都很初级, 主要是面向和我一样的初学者, 所以请各位算法帝们轻拍啊 嘎嘎 引用 已知线段1(a,b) 和线段2(c,d) ,其中a b c d为端点, 求线段交点p .(平行或共线视作不相交) 算法一: 求两条线段所在直线的交点, 再判断交点是否在两条线段上. 求直线交点时 我们可通过直线的一般方程

Pipe - POJ 1039(线段相交交点)

题目大意:有一个不反光并且不透光的管道,现在有一束光线从最左端进入,问能达到的最右端是多少,输出x坐标. 分析:刚开始做是直接枚举两个点然后和管道进行相交查询,不过这样做需要考虑的太多,细节不容易掌控.后来发现其实只需要对接口进行一下相交查询就简单多了,因为只需要考虑能不能通过每个截口就可以了,而且这样做的好处还有没有平行线和重叠线的情况,因为所有的截口都是垂直于x轴的,换一种想法海阔太空啊. 代码如下: =============================================

POJ 1127 Jack Straws ( 求直线交点, 判断线段是否相交(含端点) )

题目:传送门 题意: 给你 n 条线段的两个端点, 然后有多次询问, 每次询问, 问你线段 x 和 线段 y 是否相交. 若线段 A 和线段 B 相交且线段 A 和线段 C 相交,那么线段 B 和线段 C 相交.     1 < n < 13 题解: 暴力求线段是否相交, 然后再跑个 Floyd 或者并查集都可以的. #include <iostream> #include <stdio.h> #include <string.h> #include <

poj1039——计算几何 求直线与线段交点,判断两条直线是否相交

poj1039——计算几何  求直线与线段交点,判断两条直线是否相交 Pipe Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 9439   Accepted: 2854 Description The GX Light Pipeline Company started to prepare bent pipes for the new transgalactic light pipeline. During the de

POJ 2750 Potted Flower (单点修改求线段树上最大子序列和)

题目大意: 在一个序列上每次修改一个值,然后求出它的最大的子序列和. 思路分析: 首先我们不考虑不成环的问题.那就是直接求每个区间的最大值就好了. 但是此处成环,那么看一下下面样例. 5 1 -2 -3 4 5 那么你会发现 max = sum - min 也就是和减去最小区间和也可以得到. 所以我们最后要得到的就是两个东西.注意题目中说的不能全部取得.所以还要判断一下max 是不是等于 sum的. #include <cstdio> #include <iostream> #in

POJ&#183;1151 Atlantis&#183;线段树求矩形面积并

题目在这:http://poj.org/problem?id=1151 Atlantis Time Limit: 1000MS   Memory Limit: 10000K Description There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of parts of the is

fzu 1015 土地划分(判断线段相交+求出交点+找规律)

链接:http://acm.fzu.edu.cn/problem.php?pid=1015  Problem 1015 土地划分 Accept: 714    Submit: 1675Time Limit: 1000 mSec    Memory Limit : 32768 KB  Problem Description 在Dukeswood这块土地上生活着一个富有的农庄主和他的几个孩子.在他临终时,他想把他的土地分给他的孩子.他有许多农场,每个农场都是一块矩形土地.他在农场地图上划上一些直线将

POJ2826 An Easy Problem?!(线段交点,三角形面积)

题目链接: http://poj.org/problem?id=2826 题目描述: An Easy Problem?! Description It's raining outside. Farmer Johnson's bull Ben wants some rain to water his flowers. Ben nails two wooden boards on the wall of his barn. Shown in the pictures below, the two b