任务安排问题(贪心法)

贪心法满足条件:

1.贪心选择性
2.优化子结构


输入:S={1,2,……,n}个任务,F={[Si ,f i]},为任务的开始时间和结束时间

**输出:**S的最大相容集合(也就是如何选择任务,才能执行最多的任务?)

贪心思想:
为了选择最多的相容活动,每次选fi最小的活动,也就是结束时间最小的活动,使我们能够余下更多的时间选择更多的活动。


算法伪代码:

贪心-Activity-Selector(S,F)
n ← lenyth{1};
A ← {1}
j1
For i2 To n Do
    if si>=fj
    Then A←AU{i};ji;
Return A 

算法复杂度分析:

  • 如果结束时间已经排序
    T(n)=θ(n)

  • 如果结束时间未排序
    T(n)=θ(n)+θ(nlongn)=θ(nlongn)


C++实现代码

#include
#include
#include
using namespace std;

//任务安排问题
struct task {
    int id;
    int start;
    int finish;
};
bool cmpfinish(task t1,task t2)
{
    return t1.finish < t2.finish;
}
int main()
{
    int n;
    cin >> n;
    task Task[20];
    vector vtask;
    for (int i = 0; i < n; i++)
    {
        cin >> Task[i].id >> Task[i].start >> Task[i].finish;
    }
    //首先将任务按照结束时间非递减进行排序
    sort(Task, Task + n, cmpfinish);
    //因为第一个任务一定在最优解里面(这个可以反证法证明出来的),所以首先将第一个任务加入
    vtask.push_back(Task[0]);
    //然后看一下后面的任务,其start开始时间,有没有与前一个任务的结束时间fi重合
    int j = 0;//用来记录最新加入的任务,以便确定需要比较的finish时间。
    for (int i = j + 1; i < n; i++)
    {
        if (Task[i].start >= Task[j].finish)//需要注意等于也可以!
        {
            vtask.push_back(Task[i]);
            j = i;
        }
    }
    vector::iterator it;
    for (it = vtask.begin(); it != vtask.end(); it++)
    {
        cout << (*it).id << endl;
    }
    system("pause");
    return 0;
}

测试用例及结果

输入:
6
1 1 3
2 2 4
3 5 8
4 7 10
5 9 12
6 13 14
输出:
1
3
5
6

你可能感兴趣的:(算法基础(第五版))