【题目链接】
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最大的点。
- 证明:对于第一次选择的点 ( 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 x≥xg且y≥yg。
- 证明:假设进行了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 x≥xg且y≥yg。
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;
}










