任务调度 简单贪心

时间:2021-07-12 20:03:03

题意:

    有N个任务,每个任务都花费一个单位的时间来完成,每个任务都有规定的时间期限,超出期限完成则要罚款。求所能使罚款最小的任务组合及最小罚款金额。

   

输入:

    一个整数N代表任务个数,下面N行分别有两个整数,第一个为时间期限,第二个为超时罚款金额。

输出:

    期限内完成的任务编号,期限外完成任务编号,罚款数。


    本题关键在罚款金额,所以要尽可能的使罚款金额大的任务先完成,对任务根据罚款金额从大到小排序,依次处理各个任务。得到可提前完成的任务后,对任务根据时间期限排序,使期限大的任务尽可能的靠后,这样能保证提前完成的任务数量最大。


代码:

#include<iostream>
#include<cstring>
using namespace std ;

typedef struct test {
    int k, d, w ;
}text ;

int main(){
    text tlist [100], list [100] ;
    int p [100] ;
    int temp[1010] ;
    memset(temp, 0, sizeof(temp)) ;
    int n, i, j, t ;
    cin >> n ;
    for(i=1; i<=n; i++){
        cin >> tlist[i].d >> tlist[i].w ;
        tlist[i].k = i ;
        temp[tlist[i].w] ++ ;
    }
    for(i=2; i<=1000; i++)          //计数排序
        temp[i] += temp[i-1] ;
    for(j=n; j>=1; j--){
        list[temp[tlist[j].w]] = tlist[j] ;
        temp[tlist[j].w] -- ;
    }
    int num = 0 ;                 //提前完成任务的个数
    for(i=n; i>=1; i--){            //由于计数排序是从小到大排的,所以任务从大到小搜索
        t = 0 ;
        for(j=1; j<=num; j++)
            if(list[p[j]].d<=num)
                t ++ ;
        if(t<list[i].d){     //若第i个任务的期限小于以确定的提前完成任务个数,将第i个加入可提前完成任务序列中
            num ++ ;
            p[num] = i ;
            list[i].k = -list[i].k ;
            j = num ;
            while(j>1){             //对提前完成的任务时间期限从小到大排
                if(list[p[j]].d<list[p[j-1]].d){
                    t = p[j] ;
                    p[j] = p[j-1] ;
                    p[j-1] = t ;
                    j -- ;
                }
                else break ;
            }
        }
    }
    for(i=1; i<=num; i++)
        cout << -list[p[i]].k << " " ;
    cout << endl ;
    t = 0 ;
    for(i=1; i<=n; i++)
        if(list[i].k>0){
            cout << list[i].k << " " ;
            t += list[i].w ;
        }
    cout << endl << t ;
    return 0 ;
}