信息学奥赛一本通 1230:寻找平面上的极大点 | OpenJudge NOI 4.6 2704:寻找平面上的极大点

【题目链接】

ybt 1230:寻找平面上的极大点
OpenJudge NOI 4.6 2704:寻找平面上的极大点

【题目考点】

1. 贪心

【解题思路】

题目中的极大点,直观理解就是右上方(不包含同一横线竖线)没有其他点的点。

解法1:选择满足 x x x大于 l x lx lx的点中 y y y最大的点中 x x x最大的点

1. 贪心选择性质的证明:

l x lx lx表示上次选择的点的横坐标,初始值为-1。
对于给定的各个平面上的点 ( x , y ) (x, y) (x,y)
贪心选择:选择满足 x x x大于 l x lx lx的点中 y y y最大的点中 x x x最大的点
解释:前提条件是: x > l x x > lx x>lx,找满足这一条件的所有点中 y y y最大的点,如果有多个点 y y y同时为最大值,选其中 x x x最大的点。

  1. 证明:对于第一次选择的点 ( x g , y g ) (x_g, y_g) (xg,yg),不存在其它的点 ( x , y ) (x, y) (x,y)满足 x ≥ x g 且 y ≥ y g x \ge x_g 且 y \ge y_g xxgyyg

假设:存在点 ( x m , y m ) (x_m, y_m) (xm,ym)不为 ( x g , y g ) (x_g, y_g) (xg,yg),满足 x m ≥ x g 且 y m ≥ y g x_m \ge x_g 且 y_m \ge y_g xmxgymyg
第一次选择的点是 y y y最大的点,所以 y g ≥ y m y_g \ge y_m ygym,所以有 y g = y m y_g = y_m yg=ym
由于贪心选择为:如果 y y y最大的点有多个,那么选择其中 x x x最大的
点,所以有 x g ≥ x m x_g\ge x_m xgxm,进而 x g = x m x_g = x_m xg=xm
因此 ( x m , y m ) (x_m, y_m) (xm,ym) ( x g , y g ) (x_g, y_g) (xg,yg)是同一个点,而假设二者不是同一个点,假设不成立,原命题得证。

  1. 证明:假设进行了k次进行贪心选择,第k次贪心选择到的点的横坐标为 l x lx lx,第k+1次贪心选择,选择到点 ( x g , y g ) (x_g,y_g) (xg,yg)。证明不存在其它的点 ( x , y ) (x, y) (x,y)满足 x ≥ x g 且 y ≥ y g x \ge x_g 且 y \ge y_g xxgyyg

假设:存在点 ( x m , y m ) (x_m, y_m) (xm,ym)不为 ( x g , y g ) (x_g, y_g) (xg,yg),满足 x m ≥ x g 且 y m ≥ y g x_m \ge x_g 且 y_m \ge y_g xmxgymyg
由于 y g y_g yg是满足 x m > l x x_m>lx xm>lx的点中 y y y坐标的最大值,所以当 x m > l x x_m>lx xm>lx时不可能有 y m > y g y_m>y_g ym>yg
如果 y m > y g y_m > y_g ym>yg,那么一定有 x m ≤ l x x_m \le lx xmlx,而已知 x g > l x x_g > lx xg>lx,那么有 x g > x m x_g > x_m xg>xm,与假设相悖。
如果 y m = y g y_m = y_g ym=yg,由于 y y y相同时, x g x_g xg是其中最大的,所以有: x g ≥ x m x_g \ge x_m xgxm,进而 x g = x m x_g = x_m xg=xm,所以 ( x m , y m ) (x_m, y_m) (xm,ym) ( x g , y g ) (x_g, y_g) (xg,yg)是同一个点,这与假设相悖。
原命题得证。

2. 具体做法

将所有点排序,排序规则为:y坐标大的排在前面;如果y坐标相同,x坐标大的排在前面。
设变量lx初值为-1。
顺序遍历点的数组,选择满足x >= lx的点,如果选择了一个点,更新lx,使lx的值为这个点的横坐标。

解法2:选择满足 y y y大于 l y ly ly的点中 x x x最大的点中 y y y最大的点

该解法原理与解法1相似,不再赘述。
ly初值为-1。
由于该解法得到的点的x坐标是从大到小排列的,所以还得做一下逆序。

【题解代码】

解法1:选择满足 x x x大于 l x lx lx的点中: y y y最大的点中 x x x最大的点
#include<bits/stdc++.h>
using namespace std;
#define N 105
struct Point
{
    int x, y;
};
bool cmp(Point a, Point b)
{
    if(a.y == b.y)
        return a.x > b.x;
    else
        return a.y > b.y;
}
int main()
{
    Point a[N];
    int n, lx = -1;
    bool isFirst = true;
    cin >> n;
    for(int i = 1; i <= n; ++i)
        cin >> a[i].x >> a[i].y;
    sort(a+1, a+1+n, cmp);
    for(int i = 1; i <= n; ++i)
    {
        if(a[i].x > lx)
        {
            lx = a[i].x;
            if(isFirst)
                isFirst = false;
            else
                cout << ',';
            cout << '(' << a[i].x << ',' << a[i].y << ')';
        }
    }
	return 0;
}

解法2:选择满足 y y y大于 l y ly ly的点中: x x x最大的点中 y y y最大的点

#include<bits/stdc++.h>
using namespace std;
#define N 105
struct Point
{
    int x, y;
    bool operator < (const Point &b) const
    {//横坐标大的排在前面,横坐标相等时,纵坐标大的排在前面 
        if(x == b.x)
            return y > b.y;
        else
            return x > b.x;
    }
    void show()
    {
        printf("(%d,%d)", x, y);
    }
};
int main()
{
    vector<Point> vec;
    Point p;
    stack<Point> stk;
    int n, ly = -1;
    bool isFirst = true;
    cin >> n;
    for(int i = 1; i <= n; ++i)
    {
        cin >> p.x >> p.y;
        vec.push_back(p);
    }
    sort(vec.begin(), vec.end());
    for(int i = 0; i < n; ++i)
    {
        if(vec[i].y > ly)
        {
            ly = vec[i].y;
            stk.push(vec[i]);//从大到小得到各个点,要做逆序才能从小到大输出 
        }
    }
    while(stk.empty() == false)//逆序输出 
    {
        Point u = stk.top(); stk.pop();
        if(isFirst)
            isFirst = false;
        else
            putchar(',');
        u.show();
    } 
	return 0;
}
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值