zoukankan      html  css  js  c++  java
  • 会场安排问题

    题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=14

    经典问题。此题的最佳解法是用贪心算法:

    1) 将所有输入活动按照结束时间从早到晚排序
    2) 顺序遍历列表,将可以加入日程的活动加入,并维护活动计数
    3) 遍历完毕后,输出活动计数
    整个过程需要1) 将活动列表排序O(nlogn) 2) 遍历列表O(n),因此复杂度为O(nlogn)

    #include <iostream>
    #include
    <vector>
    #include
    <utility>
    #include
    <algorithm>
    using namespace std;

    bool Comp(const pair<int ,int > A1, const pair< int ,int > A2)
    {
    return A1.second < A2.second;
    }

    void greedySelect()
    {

    int start,finish;
    int m;
    cin
    >> m;
    while(m--){
    int n;
    cin
    >> n;
    vector
    < pair<int,int> > Avec;
    vector
    < pair<int ,int> > Svec;
    while(n-- )
    {
    cin
    >> start >> finish;
    Avec.push_back(make_pair(start,finish));
    }
    cin.clear();
    sort(Avec.begin(),Avec.end(),Comp);
    vector
    < pair<int,int> >::iterator iter = Avec.begin();
    Svec.push_back(make_pair(iter
    ->first,iter->second));
    finish
    = iter->second;
    for( ++iter;iter != Avec.end();++iter)
    if(iter->first > finish)
    {
    Svec.push_back(make_pair(iter
    ->first,iter->second));
    finish
    = iter->second;
    }
    cout
    << Svec.size() << endl;
    }
    }
    int main()
    {
    greedySelect();

    return 0;
    }

    以下是我ac的解法,没有标准解法优,在此只是存下来留个念想,其他人可以直接忽略


    我的思路是:

    1. 递归穷举(这个解法TLE,没什么价值,忽略)

    2. 贪心(基于起始时间排序)

    1) 对活动按照开始时间排序
    2) 消去不可能活动(肯定安排不到的活动)

    不可能活动的定义:在所有n个活动ai(i=1, 2 ... n)组成的集合S中,对于任意的ai∈S,若存在aj∈S(i≠j),使得b(aj)≤b(ai), e(aj)≥e(ai)(b,e代表开始时间/结束时间),则aj一定不在使得活动数最多的活动集合中,可以将其从S中删去。活动aj即为不可能活动。
    举个例子,以下几个活动集(一行为一个集合)中,只有红字的活动需要考虑,其它都可以删除。
    {3,4} {2,4} {1,4} {1,5}
    {2,3} {1,3} {2,4} {2,3}

    删除不可能活动最简单的方法就是二层嵌套循环,复杂度为O(n^2),为了降低复杂度,可以在第1) 步的排序上做一些工作。
    例如可以对活动按照(b↑e↓) 进行排序,这样可以使得在初始的几重循环中删去尽量多的元素,从而降低一些时间复杂度。

    3) 按照贪心方法安排活动

    遍历列表,将所有能够加入的活动加入。遍历完毕后,输出活动计数。

    算法需要一次排序(O(nlogn)),一次嵌套循环(O(n^2)),因此复杂度为O(n^2)

    标准解法和我的贪心解法都可以得到ac,不过标准解法在时间上明显优于我的解法。

    标准解法:时间260内存308
    我的解法:时间800内存308

    #include <iostream>
    #include
    <vector>
    #include
    <algorithm>

    using namespace std;

    typedef
    struct _AR{
    int b;
    int e;
    }AR;

    bool operator<(const AR &a, const AR &b){
    if (a.b == b.b) return a.e > b.e;
    return a.b < b.b;
    }

    vector
    <AR> arv;

    template
    < class T >
    void reverse(vector<T> &v){
    T temp;
    for (int i = 0; i < v.size()/2; i ++){
    temp
    = v[i];
    v[i]
    = v[v.size()-i-1];
    v[v.size()
    -i-1] = temp;
    }
    }

    void reduce(vector<AR> &v){

    reverse(v);

    vector
    <AR>::iterator it = v.begin();
    vector
    <AR>::iterator it2;
    while (it != v.end()){
    it2
    = it;
    it2
    ++;
    while (it2 != v.end()){
    if (it2->e >= it->e){
    v.erase(it2);
    }
    else{
    it2
    ++;
    }
    }
    it
    ++;
    }

    reverse(v);

    }

    int main()
    {

    int n;
    cin
    >>n;
    while (n--){
    arv.clear();
    int c;
    cin
    >>c;
    while (c--){
    int b, e;
    cin
    >>b>>e;
    AR a;
    a.b
    = b;
    a.e
    = e;
    arv.push_back(a);
    }
    sort(arv.begin(), arv.end());
    reduce(arv);

    int r = -1;
    int count = 0;
    for (vector<AR>::iterator it = arv.begin(); it != arv.end(); it ++){
    if (it->b > r){
    r
    = it->e;
    count
    ++;
    }
    }

    cout
    <<count<<endl;
    }

    return 0;
    }

  • 相关阅读:
    飞入飞出效果
    【JSOI 2008】星球大战 Starwar
    POJ 1094 Sorting It All Out
    POJ 2728 Desert King
    【ZJOI 2008】树的统计 Count
    【SCOI 2009】生日快乐
    POJ 3580 SuperMemo
    POJ 1639 Picnic Planning
    POJ 2976 Dropping Tests
    SPOJ QTREE
  • 原文地址:https://www.cnblogs.com/mdyang/p/2033562.html
Copyright © 2011-2022 走看看