2010年風靡全球的“水果忍者”游戲,想必大家肯定都玩過吧?(沒玩過也沒關系啦~)在游戲當中,畫面里會隨機地彈射出一系列的水果與炸彈,玩家盡可能砍掉所有的水果而避免砍中炸彈,就可以完成游戲規定的任務。如果玩家可以一刀砍下畫面當中一連串的水果,則會有額外的獎勵,如圖1所示。
圖 1
現在假如你是“水果忍者”游戲的玩家,你要做的一件事情就是,將畫面當中的水果一刀砍下。這個問題看上去有些復雜,讓我們把問題簡化一些。我們將游戲世界想象成一個二維的平面。游戲當中的每個水果被簡化成一條一條的垂直於水平線的豎直線段。而一刀砍下我們也僅考慮成能否找到一條直線,使之可以穿過所有代表水果的線段。
圖 2
如圖2所示,其中綠色的垂直線段表示的就是一個一個的水果;灰色的虛線即表示穿過所有線段的某一條直線。可以從上圖當中看出,對於這樣一組線段的排列,我們是可以找到一刀切開所有水果的方案的。
另外,我們約定,如果某條直線恰好穿過了線段的端點也表示它砍中了這個線段所表示的水果。假如你是這樣一個功能的開發者,你要如何來找到一條穿過它們的直線呢?
輸入格式:
輸入在第一行給出一個正整數N
(≤),表示水果的個數。隨后N
行,每行給出三個整數x、y1、y2,其間以空格分隔,表示一條端點為(和(的水果,其中y1>y2。注意:給出的水果輸入集合一定存在一條可以將其全部穿過的直線,不需考慮不存在的情況。坐標為區間 [ 內的整數。
輸出格式:
在一行中輸出穿過所有線段的直線上具有整數坐標的任意兩點(和(,格式為 y1。注意:本題答案不唯一,由特殊裁判程序判定,但一定存在四個坐標全是整數的解。
輸入樣例:
5
-30 -52 -84
38 22 -49
-99 -22 -99
48 59 -18
-36 -50 -72
輸出樣例:
-99 -99 -30 -52
題意:給出一些平行於y軸的線段,要求找到一條直線可以穿過(經過端點也可)所有線段,輸出直線上的兩個點,要求都是整數。
注意:如果只有一條線段,自己本身就是答案,可能存在多條直線重合,只需要記錄y最小的上端點和y最大的下端點。
方法:根據求凸包的原理,分別用棧輔助去除使得上端點連線上凸的點以及使得下端點連線下凹的點,存下剩下的點,可以連成兩條折線,那么滿足條件的直線就在兩線之間,枚舉折線的每個線段,找到滿足條件的。
輸入樣例可以得到如下圖:
黃色線是棧里保存的點連成的折線。
代碼:
#include <iostream> #include <cstdio> #include <map> #include <cstring> #include <vector> #include <algorithm> #define inf 0x3f3f3f3f using namespace std; typedef long long ll; typedef pair<int,int> pa; int n; vector<int> p; pa u[10000],d[10000]; int uc,dc; map<int,int> vis,up,down; int lx,ly,rx,ry; inline bool pupl(const pa &p1,const pa &p2,const pa &p3) { return (ll)(p3.first - p2.first) * (p2.second - p1.second) > (ll)(p2.first - p1.first) * (p3.second - p2.second); } inline bool pdownl(const pa &p1,const pa &p2,const pa &p3) { return (ll)(p3.first - p2.first) * (p2.second - p1.second) < (ll)(p2.first - p1.first) * (p3.second - p2.second); } int main() { int x,y1,y2; scanf("%d",&n); for(int i = 0;i < n;i ++) { scanf("%d%d%d",&x,&y1,&y2); if(vis[x] == 0) { p.push_back(x); vis[x] = 1; up[x] = y1; down[x] = y2; } else { up[x] = min(up[x],y1); down[x] = min(down[x],y2); } } if(p.size() == 1) { lx = p[0]; ly = up[p[0]]; rx = p[0]; ry = down[p[0]]; } else { sort(p.begin(),p.end()); for(int i = 0;i < p.size();i ++) { while(uc >= 2 && pupl(u[uc - 2],u[uc - 1],pa(p[i],up[p[i]]))) uc --; u[uc ++] = pa(p[i],up[p[i]]); while(dc >= 2 && pdownl(d[dc - 2],d[dc - 1],pa(p[i],down[p[i]]))) dc --; d[dc ++] = pa(p[i],down[p[i]]); } int i,j; for(i = 0;i < uc - 1;i ++) { for(j = 0;j < dc;j ++) { if(pupl(u[i],d[j],u[i + 1])) break; } if(j == dc) break; } if(i == uc - 1) { for(i = 0;i < dc - 1;i ++) { for(j = 0;j < uc;j ++) { if(pdownl(d[i],u[j],d[i + 1])) break; } if(j == uc) break; } lx = d[i].first; ly = d[i].second; rx = d[i + 1].first; ry = d[i + 1].second; } else { lx = u[i].first; ly = u[i].second; rx = u[i + 1].first; ry = u[i + 1].second; } } printf("%d %d %d %d",lx,ly,rx,ry); }