欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

算法-点线关系-投影在线段上各点距离最大

程序员文章站 2022-04-01 17:03:24
...

题目:

平面内有N个点,一个线段(2个顶点),一束垂直于线段的光照射后,点会在线段上有影子,求影子点里面最长距离。

输入:

第一行测试用例个数T;

第二行第一个测试用例的点个数N;

下面N行每行给出2个整数,用空格隔开表示点的x,y坐标;

再下一行给出表示光方向和大小的点坐标x,y,空格隔开;

再下一行给出线段的2个顶点左边,依次x1,y1,x2,y2,用空格隔开。

输出:

#+测试用例个数+最长的距离

**************************************************

分析:

先判断光向量的相对于线段的方向。

当光点坐标y=0,若x>0则1;否则-1;

若y>0,则-1,y<0,则1;

表示线段的方向也要保证:

若光与X轴平行,则y小的为起始点,y大的为方向

若光不与平行,则x小的为起始点,x大的为方向

使用ccw公式计算Poing A,B,C坐标,若大于0,则1;若小于0,则-1;否则0;

--------------------------------------------------------------------------

使用ccw计算点与线段的关系,保证光和点在线同侧,且投影后的点在线段上。

若投影点数少于2个,则答案为0.0;

以线段一个顶点为起点,计算满足条件的每一个点到起点的距离,然后用最大的减去最小的,得到答案。

以下是代码分析:

import java.io.*;
import java.util.*;

public class Solution{

    static int T,N;
    static Point[] points;
    static Point G;
    static Point[] L;
    static List<Point> list = new ArrayList<>();
    static double ans;

    public static void main(String[] args) throws Exception {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        T = Integer.parseInt(bf.readLine());
        for (int t = 1; t <= T; t++) {
            N = Integer.parseInt(bf.readLine());
            points = new Point[N];
            L = new Point[2];
            // get points
            for (int i = 0; i < N; i++) {
                st = new StringTokenizer(bf.readLine());
                points[i] = new Point(Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()));
            }

            //get light point
            st = new StringTokenizer(bf.readLine());
            G = new Point(Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()));

            // get Line
            st = new StringTokenizer(bf.readLine());
            Point p1 = new Point(Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()));
            Point p2 = new Point(Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()));

            if (p1.x == p2.x){
                if (p1.y < p2.y){
                    L[0] = p1;
                    L[1] = p2;
                } else {
                    L[0] = p2;
                    L[1] = p1;
                }
            } else if (p1.x < p2.x){
                L[0] = p1;
                L[1] = p2;
            } else {
                L[0] = p2;
                L[1] = p1;
            }

            method();

            System.out.println("#" + t + " " + ans);
        }
    }

    static void method(){
        list.clear();
        getMapingPoint();
        if (list.size() < 2) {
            ans = 0.0;
            return;
        }

        double[] arr = new double[list.size()];
        double dx, dy;
        for (int i = 0; i < list.size(); i++) {
            Point p = list.get(i);
            dx = p.x - L[0].x;
            dy = p.y - L[0].y;
            arr[i] = Math.sqrt(dx*dx + dy*dy);
        }
        Arrays.sort(arr);
        ans = arr[arr.length-1] - arr[0];
    }

    static void getMapingPoint(){
        int fx = getGuangFX();
        for (int i = 0; i < N; i++) {
            if (ccw(L[0], L[1], points[i]) == fx){
                check(points[i]);
            }
        }
    }

    static void check(Point p0){
        Point p1 = L[0];
        Point p2 = L[1];
        double minX = Math.min(p1.x, p2.x);
        double maxX = Math.max(p1.x, p2.x);
        double minY = Math.min(p1.y, p2.y);
        double maxY = Math.max(p1.y, p2.y);
        if (G.x == 0) {
            if (p0.x >= minX && p0.x <= maxX) {
                list.add(p0);
                return;
            }
        }

        if (G.y == 0) {
            if (p0.y >= minY && p0.y <= maxY) {
                list.add(p0);
                return;
            }
        }

        double dx = p1.x - p2.x;
        double dy = p1.y - p2.y;
        double x = (dx*dx*p0.x + dy*dy*p1.x + dx*dy*(p0.y - p1.y))/(dx*dx + dy*dy);
        double y = (dy*x + dx*p1.y - dy*p1.x) / dx;
        if (x >= minX && x <= maxX && y >= minY && y <= maxY)
            list.add(new Point(x, y));
    }

    static int getGuangFX(){
        if (G.y==0)
            return G.x > 0 ? 1 : -1;
        else
            return G.y > 0 ? -1 : 1;
    }

    static int ccw(Point A, Point B, Point C){
        double res = A.x*B.y + B.x*C.y + C.x*A.y - A.y*B.x - B.y*C.x -C.y*A.x;
        if (res > 0)
            return 1;
        else if (res <0)
            return -1;
        else
            return 0;
    }

    static class Point{
        double x;
        double y;
        public Point(double x, double y) {
            this.x = x;
            this.y = y;
        }
    }
}

 

相关标签: 算法-几何图形