选择不相交区间(贪心算法) By ACReaper
题目的分析被说得有点绕。自己理解是这样,首先由题目我们知道选择的区间都是相互不相交的,除这之外,我们的目标是尽量的让选择的区间达到最大化。
所以我们可以先对齐排序,因为输入是随机的。假设每个区间表示为(x,y)我们可以选择按照x排序所有区间,也可以选择按照y来排序所有区间。而不管选择哪一个来排序,其原理和本质都一样,都是为了方便操作,将其有序化。
我们这里选择按照y来排序,排序完后有y1 <= y2 <= y3.......
现在我们讨论x1 x2 ....
当x1 > x2时,区间被x2这个区间包含,所以选择x1这个区间更为划算。
而当x1 < x2时,当x2 > y1时,区间互不相交,先选x1区间,接着选x2区间
当x1 < x2 && x2 <=y1 时,两个区间相交,这时,如果选择了x2区间,就不能选择x1区间,反之亦然。
但要选择哪一个呢?我们知道如果不选x2也就是选x1,则我们此时把x1分成两半部分,一部分在x2内,如果选择了x2,x2区间不仅包含了x1的,还可能包含x3区间的,因为x2的长度肯定大于或等于x1区间的长度,也就是说从概率上讲,选x2肯定不如选x1划算。
综上所述:这个问题第一次一定要选择x1,接着就是把相交部分去掉,循环选不想交的。
#include <stdio.h> typedef struct zone{ int x; int y; }zone; zone A[1000]; //快速排序接口 int partition(zone A[],int st,int ed){ zone key = A[st]; int j = st; for(int i = st + 1; i <= ed; i++){ if(A[i].y <= key.y){ j++; zone temp = A[i]; A[i] = A[j]; A[j] = temp; } } zone temp = A[j]; A[j] = A[st]; A[st] = temp; return j; } void quicksort(zone A[],int st,int ed){ if(st < ed){ int mid = partition(A,st,ed); quicksort(A,mid + 1,ed); quicksort(A,st,mid - 1); } } //快速排序接口 #define MAXN 1000 int path[MAXN]; int main(){ int n; while(scanf("%d",&n) != EOF){ for(int i = 0 ; i < n; i++){ scanf("%d%d",&A[i].x,&A[i].y);//input (x,y) } quicksort(A,0,n - 1); int len = 0,i = 1; zone key = A[0]; path[len++] = 0; while(i < n){ if(key.y < A[i].x){//true 则把A[i]拓展进来 path[len++] = i; key = A[i]; } i++; } for(int i = 0; i < len; i++){ printf("(%d,%d) ",A[path[i]].x,A[path[i]].y); } } return 0; }