L3-012 水果忍者 (30分):貪心,幾何

噓......發表於2020-11-28

2010年風靡全球的“水果忍者”遊戲,想必大家肯定都玩過吧?(沒玩過也沒關係啦~)在遊戲當中,畫面裡會隨機地彈射出一系列的水果與炸彈,玩家儘可能砍掉所有的水果而避免砍中炸彈,就可以完成遊戲規定的任務。如果玩家可以一刀砍下畫面當中一連串的水果,則會有額外的獎勵,如圖1所示。
在這裡插入圖片描述

圖 1

現在假如你是“水果忍者”遊戲的玩家,你要做的一件事情就是,將畫面當中的水果一刀砍下。這個問題看上去有些複雜,讓我們把問題簡化一些。我們將遊戲世界想象成一個二維的平面。遊戲當中的每個水果被簡化成一條一條的垂直於水平線的豎直線段。而一刀砍下我們也僅考慮成能否找到一條直線,使之可以穿過所有代表水果的線段。

在這裡插入圖片描述

圖 2

如圖2所示,其中綠色的垂直線段表示的就是一個一個的水果;灰色的虛線即表示穿過所有線段的某一條直線。可以從上圖當中看出,對於這樣一組線段的排列,我們是可以找到一刀切開所有水果的方案的。

另外,我們約定,如果某條直線恰好穿過了線段的端點也表示它砍中了這個線段所表示的水果。假如你是這樣一個功能的開發者,你要如何來找到一條穿過它們的直線呢?

輸入格式:
輸入在第一行給出一個正整數N(≤10​4​​ ),表示水果的個數。隨後N行,每行給出三個整數x、y
​1​​ 、y​2​​ ,其間以空格分隔,表示一條端點為(x,y​1​​ )和(x,y​2 )的水果,其中y1 >y​2​​ 。注意:給出的水果輸入集合一定存在一條可以將其全部穿過的直線,不需考慮不存在的情況。座標為區間 [−10​6​​ ,10
​6​​ ) 內的整數。

輸出格式:
在一行中輸出穿過所有線段的直線上具有整數座標的任意兩點p​1​​ (x​1​​ ,y​1​​ )和p​2​​ (x​2​​ ,y​2),格式為 x
​1y1x​2​​ y​2。注意:本題答案不唯一,由特殊裁判程式判定,但一定存在四個座標全是整數的解。

輸入樣例:
5
-30 -52 -84
38 22 -49
-99 -22 -99
48 59 -18
-36 -50 -72
輸出樣例:
-99 -99 -30 -52
貪心,找到符合要求的那條連線一條線的最高點和另一條線的最低點的斜線

#include <bits/stdc++.h>
using namespace std;
#define ll long long
double x[10010],yl[10010],yh[10010],a,b,p,q,t,xx,yy;
int n,c;
int main()
{
    //ios::sync_with_stdio(false);
    cin>>n;
    for(int i=1;i<=n;i++)
     cin>>x[i]>>yh[i]>>yl[i];
    for(int i=1;i<=n;i++)
    {
    	p=0x3f3f3f3f;q=-0x3f3f3f3f;
    	int j;
    	for(j=1;j<=n;j++)
    	 if(i!=j)
    	 {
    	 	a=(yh[j]-yl[i])/(x[j]-x[i]);//大斜率 
    	 	b=(yl[j]-yl[i])/(x[j]-x[i]);//小斜率 
    	 	if(a<b) //直線j在直線i左邊 
    	 	{
    	 		swap(a,b);
    	 		c=0;
			}
			else c=1;
			if(p<b||q>a) break;
			if(a<p)
			{
				p=a;
				if(c) yy=yh[j],xx=x[j];
				else yy=yl[j],xx=x[j];
			}
			q=max(q,b);
		 }
		 if(j==n+1)
		 {
		 	printf("%.0lf %.0lf %.0lf %.0lf",x[i],yl[i],xx,yy);
		 	return 0;
		 }
	}
    return 0;
}

相關文章