高端购物网站有趣软文广告经典案例
数轴上有n个闭区间[ai,bi]。取尽量少的点,使得每个区间内都至少有一个点(不同区间内含的点可以是同一个)。
贪心策略:
按照b1<=b2<=b3…(b相同时按a从大到小)的方式排序排序,从前向后遍历,当遇到没有加入集合的区间时,选取这个区间的右端点b。
证明:
为了方便起见,如果区间i内已经有一个点被取到,我们称区间i被满足。
1、首先考虑区间包含的情况,当小区间被满足时大区间一定被满足。所以我们应当优先选取小区间中的点,从而使大区间不用考虑。
按照上面的方式排序后,如果出现区间包含的情况,小区间一定在大区间前面。所以此情况下我们会优先选择小区间。
则此情况下,贪心策略是正确的。
2、排除情况1后,一定有a1<=a2<=a3……。
对于区间1来说,显然选择它的右端点是明智的。因为它比前面的点能覆盖更大的范围。
从而此情况下,贪心策略也是正确的。
例题:http://acm.nyist.net/JudgeOnline/problem.php?pid=287
附代码(非此例题代码)。(和选择不相交区间问题的十分相似)
#include <stdio.h>
#include <algorithm>
using namespace std;
struct Extent
{int a,b;bool operator < (const Extent& S)const{return b < S.b || b == S.b && a > S.a;}
}A[10002];
int main()
{int z,n,cnt,end;scanf("%d",&z);while(z--){cnt = 0;end = -1;scanf("%d",&n);for(int i=0;i<n;i++)scanf("%d%d",&A[i].a,&A[i].b);sort(A,A+n);for(int i=0;i<n;i++){if(end < A[i].a){end = A[i].b;cnt++;}}printf("%d\n",cnt);}return 0;
}