为下一个问题找到算法: 给定2D平面中的n个点的集合S,如果x1> 1,则点(x1,y1)支配另一个点(x2,y2)。 x2和y1> Y2。找到最大的点集M,使得M是S的子集,并且M的任何点都不被S的另一个点支配。
答案 0 :(得分:8)
通过增加x坐标对所有点进行排序。如果两个点具有相同的x坐标,则通过减小y坐标对它们进行排序。现在,可以证明,当且仅当它们的y坐标在我们的排序序列中不增加时,一个点的子集是非支配的,这意味着每个y坐标小于或等于子序列中的前一个坐标。
所以算法是:
这为O(n * logn)提供了最大可能的设置。
答案 1 :(得分:1)
在O(n * logn)时间内有一个分而治之的算法。
根据它们的x坐标,将这些点分成两半,每个大小为n / 2。我们在两个半部分中找到了非支配点。您需要观察到在右半部分找到的所有非支配点都将存在于我们的最终列表中。
通过这个观察,我们可以编写我们的组合步骤,删除左半部分中所有非支配点,其中y坐标小于右半部分非支配集合中点的最高y坐标。我们有一组非支配点。
<强>算法:强>
Find the median along x axis - O(n) time
Find non-dominated points in the left half - T(n/2)
Find non-dominated points in the right half - T(n/2)
set of non-dominated points could be on O(n) so, the combine step might have to check O(n) points
时间等式:
T(n) = 2T(n/2) + O(n) which is O(n*logn)
你可以进一步改进O(n * logH),其中H是非支配点的数量,它需要更深入地了解问题,这对你来说是一个很好的扩展。
答案 2 :(得分:0)
#include <bits/stdc++.h>
using namespace std;
bool comp(pair<int,int> a,pair<int,int> b) {
if(a.first<b.first)
return true;
else if(a.first==b.first) {
if(a.second<b.second)
return true;
else
return false;
}
return false;
}
int main() {
int n,x,y;
cin>>n;
vector <pair<int,int>> points;
vector <int> brr;
for( int i=1;i<=n;i++ ) {
cin>>x>>y;
points.push_back({x,y});
}
if(n==1) {
cout<<"1\n";
return 0;
}
sort(points.begin(),points.end(),comp);
priority_queue <int> point_y;
for( int i=n-1;i>=0;i-- ) {
while(!point_y.empty()) {
if(point_y.top()>points[i].second)
point_y.pop();
}
if(i>=1&&points[i].first==points[i-1].first) {
brr.push_back(points[i].second);
}
else {
point_y.push(points[i].second);
for(int it : brr )
point_y.push(it);
brr.clear();
}
}
cout<<point_y.size()<<endl;
}
这可能对您有帮助。
我在做什么。首先对点(x1<x2) || (x1==x2&&y1<y2)
进行排序
然后从末端进行迭代,从y大于该点的priority_queue中弹出