猪猪大厦

题目描述

平面上有 n个无限长的不垂直或平行于地面的扶手电梯,可以看做一些一次函数,并且这些电梯方向均朝右即 x 轴正方向

两个电梯的交点可以花费1代价换乘

此时人物在第(x_1)个电梯的横坐标为$ y_1$ 位置。

( exttt{piggy})在第 (x_2)个电梯的横坐标为 (y_2) 位置。

请问他最少花多少 代价才能过去?

输入格式

第一行一个正整数 n。

第二行四个整数 x_1,y_1,x_2,y_2 。

接下来 n 行,第 i 行两个数 k_i,b_i ,表示电梯的解析式为 y=k_ix+b_i

输出格式

最少花多少 代价如果无法到达,输出 -1。

输入输出样例

输入 #1

1

1 1 1 2

50 -30

输出 #1

0

输入 #2

2

1 2 2 2

1 0

2 0

输出 #2

-1

输入 #3

2

1 -1 2 1

1 0

2 0

输出 #3

1

说明/提示

本题采用 Subtask。

(Subtask1(20pts):1 le n le 10)

(Subtask2(30pts):1 le nle 1000)

(Subtask3(50pts):1 le x_1,x_2 le nle 10^5\-10^3 le y_1,y_2,k_i,b_i le 10^3)

题目分析

首先是结论:如果能到目标点,那么最多转换2次即可到达

然后是特殊情况,如下:

令起终点为(x1,y1),(x2,y2)

  1. 起点终点在同一直线,代价为0
  2. 起点所在直线(l_1)与终点所在直线(l_2)交点位于x1,x2之间,可以直接换乘1次
  3. 起终点直线交点不满足条件,通过第三方直线换乘2次。枚举换乘直线,判断交点顺序是否从左到右

本题需要通过平面几何,考虑特殊情况

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
struct Line
{
    int k, b;
} lines[100005];
int n;
int sx, sy, ex, ey;
double getCrossX(int l1, int l2)
{
    return (lines[l2].b - lines[l1].b)*1.0 / (lines[l1].k - lines[l2].k);
}
int main()
{
    int l1, l2;
    double x1,x2;
    cin >> n;
    cin >> l1 >> x1 >> l2 >> x2;
    //注意数组是从0开始的
    l1--;l2--;
    for (int i = 0; i < n; i++)
    {
        scanf("%d%d", &lines[i].k, &lines[i].b);
    }
    sx = x1;
    ex = x2;
    //特判ans=0
    if (l1 == l2 && x1 <= x2)
    {
        cout << 0;
        return 0;
    }
    //特判ans=1
    if (lines[l1].k != lines[l2].k)
    {
        double cx = getCrossX(l1, l2);
        if (sx <= cx && ex >= cx)
        {
            cout << 1;
            return 0;
        }
    }else if (lines[l1].b==lines[l2].b){
        if (sx<=ex){
            cout<<1;
            return 0;
        }else{
            cout<<-1;
            return 0;
        }
    }
    //ans=2枚举过渡线
    for (int i = 0; i < n; i++)
        if (i != l1 && i != l2)
        {
            if (lines[l1].k != lines[i].k && lines[i].k != lines[l2].k)
            {
                double cx1 = getCrossX(l1, i);
                double cx2 = getCrossX(i, l2);
                if (cx1 <= cx2 && x1 <= cx1 && x2 >= cx2)
                {
                    cout << 2;
                    return 0;
                }
            }
        }
    cout << -1;
}
原文地址:https://www.cnblogs.com/Y-E-T-I/p/15129613.html