贪心算法之区间调度问题

来源:互联网 发布:java构造器 编辑:程序博客网 时间:2024/05/17 16:53
问题主题:区间调度问题
问题描述:
有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;}


0 0
原创粉丝点击