【题解】【信奥一本通T1230】【贪心】——寻找平面上的极大点
寻找平面上的极大点
题目描述
在一个平面上,如果有两个点 ( x , y ) (x,y) (x,y), ( a , b ) (a,b) (a,b),如果说 ( x , y ) (x,y) (x,y)支配了 ( a , b ) (a,b) (a,b),这是指 x ≥ a x\geq a x≥a, y ≥ b y\geq b y≥b;
用图形来看就是 ( a , b ) (a,b) (a,b)坐落在以 ( x , y ) (x,y) (x,y)为右上角的一个无限的区域内。
给定 n n n个点的集合,一定存在若干个点,它们不会被集合中的任何一点所支配,这些点叫做极大值点。
编程找出所有的极大点,按照 x x x坐标由小到大,输出极大点的坐标。本题规定: n n n不超过 100 100 100,并且不考虑点的坐标为负数的情况。
输入格式
输入包括两行,第一行是正整数
n
n
n,表示是点数,第二行包含
n
n
n个点的坐标。
坐标值都是整数,坐标范围从
0
0
0到
100
100
100,输入数据中不存在坐标相同的点。
输出格式
按
x
x
x轴坐标最小到大的顺序输出所有极大点。
输出格式为:
(
x
1
,
y
1
)
(x_1,y_1)
(x1,y1),
(
x
2
,
y
2
)
(x_2,y_2)
(x2,y2),…
(
x
k
,
y
k
)
(x_k,y_k)
(xk,yk)。
注意:输出的每个点之间有,
分隔,最后一个点之后没有,
,少输出和多输出都会被判错。
输入输出样例
输入 #1
5
1 2 2 2 3 1 2 3 1 4
输出 #1
(1,4),(2,3),(3,1)
提示
解法1.暴力枚举
1.1.题意解析
直接暴力枚举所有点,如果这个点被"支配",那么就标记。否则就在后面直接输出。不过多阐述。
1.2.AC代码
#include<bits/stdc++.h>
using namespace std;
#define MAXN 110
int n,tot,vis[MAXN];//用vis标记这个点是否不是"极大点"
struct point//储存每一个点的信息
{
int x,y;
}a[MAXN];
bool cmp(point a,point b)//输出需要,排序规则
{
if(a.x==b.x)return a.y<b.y;
else return a.x<b.x;
}
int main()
{
scanf("%d",&n);tot=n;//用tot储存"极大点"的个数
for(int i=1;i<=n;i++)scanf("%d%d",&a[i].x,&a[i].y);
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)//循环判断是否被"支配"
if(a[i].x<=a[j].x&&a[i].y<=a[j].y&&i!=j)
{//如果被"支配"
vis[i]=1;
tot--;
break;
}
for(int i=1,j=1;i<=n&&j<=tot;i++)
if(!vis[i])//不被任何点支配,就是"极大点"
{
printf("(%d,%d)",a[i].x,a[i].y);
if(j++<tot)putchar(',');//不是最后一个点,输出,
}
return 0;
}
解法2.贪心
2.1.题意解析
上述做法的时间复杂度是 O ( n 2 ) O(n^2) O(n2),还有没有改进的办法?
观察上面的这张图(给你们搬到下面来了)
如果将这张图倒过来看,将是这样的场景。(将就着看吧)
我们可以考虑将每一个点按y坐标从大到小排序。在后面的遍历中,除非有点能超过它的
x
x
x坐标,不然就绝对会被它支配
。读者可以自行思考并设法证明。
在代码实现中,使用一个变量lastx
记录当前最后一次贪心选择
的
x
x
x坐标。其他就没什么好讲的了。这种办法可以将时间复杂度
降到
O
(
n
log
n
)
O(n\log n)
O(nlogn)(排序)。只可意会不可言传,直接看代码。
2.2.AC代码
#include<bits/stdc++.h>
using namespace std;
#define MAXN 110
struct point//储存每一个点的信息
{
int x,y;
}a[MAXN];
bool cmp(point a,point b)
{
if(a.y==b.y)return a.x>b.x;
return a.y>b.y;//优先按y坐标排序
}
int main()
{
int n,lastx=-1,is_first=1;
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>lastx)//符合条件
{
lastx=a[i].x;
if(is_first)is_first=false;
else putchar(',');
printf("(%d,%d)",a[i].x,a[i].y);
}
return 0;
}
喜欢就订阅此专辑吧!
【蓝胖子编程教育简介】
蓝胖子编程教育,是一家面向青少年的编程教育平台。平台为全国青少年提供最专业的编程教育服务,包括提供最新最详细的编程相关资讯、最专业的竞赛指导、最合理的课程规划等。本平台利用趣味性和互动性强的教学方式,旨在激发孩子们对编程的兴趣,培养他们的逻辑思维能力和创造力,让孩子们在轻松愉快的氛围中掌握编程知识,为未来科技人才的培养奠定坚实基础。
欢迎扫码关注蓝胖子编程教育