寻找下一个问题的算法: 给定二维平面上的n个点的集合S,如果x1 > x2且y1 > y2,则点(x1,y1)支配另一个点(x2,y2)。找到最大的点集M,使得M是S的子集,并且M中没有任何点被S中的另一个点支配。
有一种分治算法可以在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)
#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大于该点的值
O(2^n)
更差的复杂度。 - John Dvorak