我试图解决这个问题here。
此外,发布问题:您将获得N个间隔的列表。 挑战是选择最大的间隔子集,使得子集中没有三个间隔共享一个公共点?
但无法解决问题。这是我到目前为止所尝试的:
你们可以给我一些关于如何解决这个问题的提示,或者我是否遗漏了什么。对不起,我在很长一段时间后都在做算法,最近一直没见。
答案 0 :(得分:3)
我会在没有编程的情况下给出解决方案。
让我们将段表示为s 1 ,s 2 ,...,s n 。它们的开头为b 1 ,b 2 ,... b n ,它们的结尾为e 1 , e 2 ,... e n 。
按段开头对段进行排序,因此b 1 < B'的子> 2 子>< ...< B'的子>名词子>。如果没有三个段覆盖一个点的条件成立,则足以检查它们。我们将按照从b 1 到b n 的顺序进行。所以,从b 1 开始,移动到下一个点,依此类推,直到某个点b i 有三个段覆盖它。这些将是段s i 和另外两个,假设s j 和s k 。在这三个段中删除具有最大终点的段,即max {e i ,e j ,e k }。移到下一个段的开头(b i + 1 )。当我们到达b n 时,过程就完成了。剩下的所有段构成了段的最大子集,因此没有三个段共享一个公共点。
为什么这将是最大子集。假设我们的解决方案是S(段的集合)。假设存在最优解S *。再次,按S开头的坐标对S和S *中的线段进行排序。现在,我们将浏览S和S *中的段并比较它们的终点。通过在S中对任何k th 段构造S,其末端坐标小于S *中的k th 段的末端坐标(e k 子>&LT; = E <子>ķ子> )。因此,S中的段数不小于S (在S *中移动我们总是超越S)。
如果这还不够令人信服,那么首先尝试考虑一个更简单的问题,其中没有两个段可以重叠。解决方案是相同的,但它更直观地看出为什么它给出了正确的答案。
答案 1 :(得分:2)
Shafa是对的;
#include <iostream>
#include <set>
using namespace std;
class Interval{
public:
int begin;int end;
Interval(){
begin=0;end=0;
}
Interval(int _b,int _e){
begin=_b;end=_e;
}
bool operator==(const Interval& i) const {
return (begin==i.begin)&&(end==i.end);
}
bool operator<(const Interval& i) const {
return begin<i.begin;
}
};
int n,t,a,b;
multiset<Interval> inters;
multiset<int> iends;
multiset<Interval>::iterator it1;
multiset<int>::iterator et1;
int main(){
scanf("%d",&t);
while(t--){
inters.clear();
iends.clear();
scanf("%d",&n);
while(n--){
scanf("%d %d",&a,&b);
Interval inter(a,b);
inters.insert(inter);
}
it1=inters.begin();
while(it1!=inters.end()){
iends.insert(it1->end);
et1=iends.lower_bound(it1->begin);
multiset<int>::iterator t=et1;
if((++et1!=iends.end())&&(++et1!=iends.end())){
//æŠŠå‰©ä¸‹çš„çº¿æ®µå…¨éƒ¨åˆ æŽ‰
while(et1!=iends.end()){
multiset<int>::iterator te=et1;
et1++;
iends.erase(te);
}
}
it1++;
}
printf("%d\n",iends.size());
}
system("pause");
return 0;
}