L3_12水果忍者

这个题是一个思维题

首先看需求,找一个直线,能够成功割到所有垂直的直线,并输出这条直线上的任意两个整数点

所以我们应该先去找直线,然后再自己确定一个小规则,找到固定的点

这里我们选择了(a[i].x,a[i].miny)作为最开始的点,也就是从一个选中的水果上的最下面的点去枚举其余直线,来确定answer line的斜率,对于两个直线来说最大斜率和最小斜率一定是maxy和miny的交叉连线,但是我们需要满足的需求是最后需要给出两个整数点,所以我们固定了a[i].miny这个点,去与a[j].maxy和a[j].miny相连,得到斜率的范围,也就是这个斜率范围的所有直线,一定过a[i].x,a[i].miy这个点

L3-012 水果忍者 (30分)

2010年风靡全球的“水果忍者”游戏,想必大家肯定都玩过吧?(没玩过也没关系啦~)在游戏当中,画面里会随机地弹射出一系列的水果与炸弹,玩家尽可能砍掉所有的水果而避免砍中炸弹,就可以完成游戏规定的任务。如果玩家可以一刀砍下画面当中一连串的水果,则会有额外的奖励,如图1所示。

图 1

现在假如你是“水果忍者”游戏的玩家,你要做的一件事情就是,将画面当中的水果一刀砍下。这个问题看上去有些复杂,让我们把问题简化一些。我们将游戏世界想象成一个二维的平面。游戏当中的每个水果被简化成一条一条的垂直于水平线的竖直线段。而一刀砍下我们也仅考虑成能否找到一条直线,使之可以穿过所有代表水果的线段。

图 2

如图2所示,其中绿色的垂直线段表示的就是一个一个的水果;灰色的虚线即表示穿过所有线段的某一条直线。可以从上图当中看出,对于这样一组线段的排列,我们是可以找到一刀切开所有水果的方案的。

另外,我们约定,如果某条直线恰好穿过了线段的端点也表示它砍中了这个线段所表示的水果。假如你是这样一个功能的开发者,你要如何来找到一条穿过它们的直线呢?

输入格式:

输入在第一行给出一个正整数N(≤10​4​​),表示水果的个数。随后N行,每行给出三个整数x、y​1​​、y​2​​,其间以空格分隔,表示一条端点为(x,y​1​​)和(x,y​2​​)的水果,其中y​1​​>y​2​​。注意:给出的水果输入集合一定存在一条可以将其全部穿过的直线,不需考虑不存在的情况。坐标为区间 [−10​6​​,10​6​​) 内的整数。

输出格式:

在一行中输出穿过所有线段的直线上具有整数坐标的任意两点p​1​​(x​1​​,y​1​​)和p​2​​(x​2​​,y​2​​),格式为 x​1​​y​1​​x​2​​y​2​​。注意:本题答案不唯一,由特殊裁判程序判定,但一定存在四个坐标全是整数的解。

输入样例:

5
-30 -52 -84
38 22 -49
-99 -22 -99
48 59 -18
-36 -50 -72

 

输出样例:

-99 -99 -30 -52
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f
struct node
{
    double x,maxy,miny;
}a[10015];
int n;
double ansx,ansy,maxk,mink,ansmaxk,ansmink,u,v1,v2;
bool cmp(node c,node d)
{
    return c.x<d.x;
}
int main()
{
    cin>>n;
    for(int i = 0; i < n; i++)
    {
        scanf("%lf %lf %lf",&u,&v1,&v2);
        a[i].x = u;
        a[i].maxy = v1;
        a[i].miny = v2;
    }
    sort(a,a+n,cmp);
    bool flag;
    for(int i = 0; i < n; i++)
    {
        ansmaxk = INF;
        ansmink = -INF;
        flag = false;
        for(int j = 0; j < n; j++)
        {
            if(i != j)
            {
                if(i < j)
                {
                    maxk = (a[i].miny - a[j].maxy)/(a[i].x - a[j].x);
                    mink = (a[i].miny - a[j].miny)/(a[i].x - a[j].x);
                }
                else
                {
                    mink = (a[i].miny - a[j].maxy)/(a[i].x - a[j].x);
                    maxk = (a[i].miny - a[j].miny)/(a[i].x - a[j].x);
                }
                if(maxk < ansmink || mink > ansmaxk)
                {
                    flag = true;
                    break;
                }
                if(ansmaxk > maxk)
                {
                    ansmaxk = maxk;
                    ansx = a[j].x;
                    ansy = a[j].maxy;
                }
                ansmink = max(ansmink,mink);
            }
        }
        if(!flag)
        {
            printf("%0.0f %0.0f %0.0f %0.0f\n",a[i].x,a[i].miny,ansx,ansy);
            break;
        }
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值