贪心算法之区间调度问题

问题主题:区间调度问题
问题描述:
有n项工作,每项工作分别在si开始,ti结束。对每项工作,你都可以选择参加或不参加,但选择了参加某项工作就必须至始至终参加全程参与,即参与工作的时间段不能有重叠(即使开始的时间和结束的时间重叠都不行)。
限制条件:
1<=n<=100000
1<=si<=ti,=109
样例:
输入
n=5
s={1,2,4,6,8}
T={3,5,7,9,10}
输出

3(选择工作1, 3, 5)

对这个问题,如果使用贪心算法的话,可能有以下几种考虑:

(1)、每次选取开始时间最早的;

(2)、每次选取结束时间最早的;

(3)、每次选取用时最短的;

(4)、在可选工作中,每次选取与最小可选工作有重叠的部分;

对于上面的四种算法,只有算法(2)是正确的,其它的三种都可以找到相应的反例。具体证明如下:

 

数轴上有n个区间,选出最多的区间,使得这些区间不互相重叠。

算法:

将所有区间按右端点坐标从小到大排序,顺序处理每个区间。如果它与当前已选的所有区间都没有重叠,则选择该区间,否则不选。

代码如下:

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN=100000;
pair<int,int> itv[MAXN];
int main()
{
    int i,j,n,s[MAXN],t[MAXN],tt=0,ans=0;//tt是所选工作的结束时间
    scanf("%d",&n);
    for(i=0;i<n;i++)
    {
        scanf("%d",&s[i]);
    }
    for(j=0;j<n;j++)
    {
        scanf("%d",&t[j]);
    }
    sort(itv,itv+n);
    for(i=0;i<=n;i++)//为了让结束时间早的工作排在前面,把t存在first,s存在second
    {
        itv[i].first=t[i];
        itv[i].second=s[i];
    }
    for(i=0;i<n;i++)
    {
        if(tt<itv[i].second)
        {
            ans++;
            tt=itv[i].first;
        }
    }
    cout<<ans<<endl;
    return 0;

}


posted @ 2015-07-25 14:04  Zeroinger  阅读(538)  评论(0编辑  收藏  举报
无觅关联推荐,快速提升流量