【题目描述】
我们定义一个整数区间[a,b],a,b是一个从a开始至b 结束的连续整数的集合。编一个程序,对给定的 n个区间,找出满足下述条件的所含元素个数最少的集合中元素的个数:对于所给定的每一个区间,都至少有两个不同的整数属于该集合。(1<=n<=10000, 0<=a<=b<=1000)
输入输出格式:
输入:第一行一个正整数n,接下来有n行,每行给定一个区间的a,b值
输出:一个正整数,即满足条件的集合所包含的最少元素个数
输入输出样例
输入: 输出:
4 4
3 6
2 4
0 2
4 7
【算法分析】
本题数据规模较大,用搜索做会超时,而动态规划无从下手。考虑贪心算法。题目意思是要找一个集合,该集合中的数的个数既要少又要和所给定的所有区间有交集。(每个区间至少有两个该集合中的数)。我们可以从所给的区间中选数,为了选尽量少的数,应该使所选的数和更多的区间有交集这就是贪心的标准。一开始将所有区间按照右端点从小到大排序。从第一个区间开始逐个向后检查,看所选出的数与所查看的区间有无交集,有两个则跳过,只有一个数相交,就从当前区间中选出最大的一个数(这里有个陷阱,若原相交数为最后一个,则去前一个数),若无交集,则从当前区间选出两个数,就(右端点,右端点-1),直至最后一个区间。
也不知道哪个OJ有这个题目,所以不知道代码对不对
1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 using namespace std; 5 struct s 6 { 7 int l,r; 8 }; 9 10 bool vv(const s &a,const s &b) 11 { 12 return a.r < b.r; 13 } 14 int main() 15 { 16 int n; 17 cin>>n; 18 vector <s> v(n); 19 for (int i = 0; i < n;i++) 20 { 21 cin>>v[i].l>>v[i].r; 22 } 23 vector <int> aim; 24 sort(v.begin(),v.end(),vv); 25 for (int i = 0; i < n;i++) 26 { 27 int num = 0; 28 bool flag = 0; 29 for (int j = v[i].l; j <= v[i].r;j++) 30 { 31 if (find(aim.begin(),aim.end(),j) != aim.end()) 32 { 33 num++; 34 if ( *find(aim.begin(),aim.end(),j) == v[i].r) 35 flag =1; 36 } 37 } 38 if (num == 0) 39 { 40 aim.push_back(v[i].r); 41 aim.push_back(v[i].r-1); 42 } 43 else if (num == 1 && flag ==0) 44 { 45 aim.push_back(v[i].r); 46 } 47 else if (num == 1 &&flag ==1) 48 aim.push_back(v[i].r-1); 49 } 50 cout<<aim.size()<<endl; 51 return 0; 52 }