0
点赞
收藏
分享

微信扫一扫

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

跟着Damon写代码 2022-03-31 阅读 12
c++

【题目链接】

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

【题目考点】

1. 贪心

【解题思路】

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

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

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
  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

2. 具体做法

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

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

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

【题解代码】

解法1:选择y最大的点,如果y相同,选择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最大的点

#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;
}
举报

相关推荐

0 条评论