【算法学习笔记】51. 贪心法 区间排序问题 SJTU OJ 1360 偶像丁姐的烦恼

Description

成为LL冠军的人气偶像丁姐最近比较烦,许多商业活动找上门来。因为每次商业活动给的毛爷爷都一样,所以丁姐希望能够尽可能多的参加这些活动。然而,商业活动的起止时间并不由丁姐说了算,因此丁姐想写一个程序,求出他最多能够参加的商业活动的数量。

Input Format

第一行一个数n,表示可选活动的数量。

接下n行每行两个数,表示每个活动开始时间t1_i和结束的时间t2_i。

Output Format

一个数字,表示丁姐最多能够参加的活动的数量。

Sample Input

10
0 3
0 5
10 13
12 15
2 6
4 8
9 11
13 18
14 16
15 20

Sample Output

5

Hint

样例选取的活动时间为:(0, 3), (4, 8), (9, 11), (12, 15), (15, 20)

n≤100000

0≤t1_i<t2_i≤1000000

 
 
 
 
思路1.按左端排序 (同左则按右)
错误代码如下:
#include <iostream>
#include <algorithm>
using namespace std;
 
struct Period
{
    int start;
    int end;
};
 
//按照start排序
int cmp_period(const void* _a, const void* _b){
    Period* a = (Period*) _a;
    Period* b = (Period*) _b;
    if((*a).start != (*b).start)
        return (*a).start - (*b).start;
       else
        return (*a).end - (*b).end;
}
 
Period ps[100001];
 
int main(int argc, char const *argv[])
{
    
    int n;
    cin>>n;
    for (int i = 0; i < n; ++i){
        
        cin>>ps[i].start>>ps[i].end;
    }
    
    qsort(ps,n,sizeof(Period),cmp_period);
    
    // for (int i = 0; i < n; ++i)
    // {
    //     cout<<ps[i].start<<" "<<ps[i].end<<endl;
    // }
    
    int cur = ps[0].start;
    int index = 0;
    int ans = 1;
    while(1){
        cur = ps[index].end;
        index++;
        for(;index < n; index++){
            if(ps[index].start >= cur){
                if(index<n-1 and ps[index+1].end < ps[index].end)
                    index++;
                ans++;
                break;
            }
        }
        if(index >= n-1)
            break;
    }
    cout<<ans<<endl;
    return 0;
}
错误代码1
样例经过排序后则是
0 3
0 5
2 6
4 8
9 11 
10 13
12 15
13 18
14 16
15 20
 
第一直觉是先选择第一个区间,然后选择左端点大于等于第一个区间右端点的第一个区间,(4,8) 然后以此类推。因为同样的起点里,肯定选择的是尾部更小的。
但是这种方法会产生一个问题就是,遇到了完全重合区间没有办法延伸。
比如
0 3
3 9
4 8
8 9
按刚才的算法回选择 0 3, 3 9 但是实际上应该是 0 3, 4 8, 8 9
原因在于4,8是完全含于3,9的,所以我们要选择4,8并继续进行下去
 
原文地址:https://www.cnblogs.com/yuchenlin/p/sjtu_oj_1360.html