2010年风靡全球的“水果忍者”游戏,想必大家肯定都玩过吧?(没玩过也没关系啦~)在游戏当中,画面里会随机地弹射出一系列的水果与炸弹,玩家尽可能砍掉所有的水果而避免砍中炸弹,就可以完成游戏规定的任务。如果玩家可以一刀砍下画面当中一连串的水果,则会有额外的奖励,如图1所示。
现在假如你是“水果忍者”游戏的玩家,你要做的一件事情就是,将画面当中的水果一刀砍下。这个问题看上去有些复杂,让我们把问题简化一些。我们将游戏世界想象成一个二维的平面。游戏当中的每个水果被简化成一条一条的垂直于水平线的竖直线段。而一刀砍下我们也仅考虑成能否找到一条直线,使之可以穿过所有代表水果的线段。
如图2所示,其中绿色的垂直线段表示的就是一个一个的水果;灰色的虚线即表示穿过所有线段的某一条直线。可以从上图当中看出,对于这样一组线段的排列,我们是可以找到一刀切开所有水果的方案的。
另外,我们约定,如果某条直线恰好穿过了线段的端点也表示它砍中了这个线段所表示的水果。假如你是这样一个功能的开发者,你要如何来找到一条穿过它们的直线呢?
输入格式:
输入在第一行给出一个正整数N
(≤104),表示水果的个数。随后N
行,每行给出三个整数x、y1、y2,其间以空格分隔,表示一条端点为(x,y1)和(x,y2)的水果,其中y1>y2。注意:给出的水果输入集合一定存在一条可以将其全部穿过的直线,不需考虑不存在的情况。坐标为区间 [−106,106) 内的整数。
输出格式:
在一行中输出穿过所有线段的直线上具有整数坐标的任意两点p1(x1,y1)和p2(x2,y2),格式为 x1y1x2y2。注意:本题答案不唯一,由特殊裁判程序判定,但一定存在四个坐标全是整数的解。
输入样例:
5
-30 -52 -84
38 22 -49
-99 -22 -99
48 59 -18
-36 -50 -72
输出样例:
-99 -99 -30 -52
分析:将所有水果信息按照x轴顺序排列好,枚举每一条水果线段,以最它的最低点作为参照点,然后取和其他所有线段点所成直线的交集。如果与所有的水果都有公共的斜率交集,说明存在以枚举线段最低点为刀砍线上的一个点。方便起见,选取其余线段最大斜率的最小值作为目标直线上的另外一个点,即为答案~Fruit中存储每个水果的坐标信息,kmax表示从枚举点出发能经过所有线段的直线的最大斜率,kmin表示从枚举点出发能经过所有线段的直线的最小斜率,tkmax、tkmin为两个水果之间的最大、最小斜率~
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
#include <bits/stdc++.h> using namespace std; struct node { double x, y1, y2; bool friend operator < (const node &a, const node &b) { return a.x < b.x; } }Fruit[10000]; int n, hx, hy; double kmax, kmin, tkmax, tkmin; int main() { cin >> n; for (int i = 0; i < n; i++) cin >> Fruit[i].x >> Fruit[i].y1 >> Fruit[i].y2; sort(Fruit, Fruit + n); for (int i = 0, j; i < n; i++) { kmax = 1e9, kmin = -1e9; for (j = 0; j < n; j++) { if (i == j) continue; if (i < j) { tkmax = (Fruit[j].y1 - Fruit[i].y2) / (Fruit[j].x - Fruit[i].x); tkmin = (Fruit[j].y2 - Fruit[i].y2) / (Fruit[j].x - Fruit[i].x); } else { tkmax = (Fruit[i].y2 - Fruit[j].y2) / (Fruit[i].x - Fruit[j].x); tkmin = (Fruit[i].y2 - Fruit[j].y1) / (Fruit[i].x - Fruit[j].x); } if (tkmax < kmin || tkmin > kmax) break; if (tkmax < kmax) { kmax = tkmax; hx = Fruit[j].x; hy = Fruit[j].y1; } kmin = max(kmin, tkmin); } if (j == n) { cout << hx << ' ' << hy << ' ' << (int)Fruit[i].x << ' ' << (int)Fruit[i].y2; break; } } return 0; } |
❤ 点击这里 -> 订阅《PAT | 蓝桥 | LeetCode学习路径 & 刷题经验》by 柳婼