C++实现使用贪心法解决机器作业问题

问题描述:
n n n 个作业需要在一台机器上执行,一个时刻机器上只能执行一个作业,每个作业可在单位时间内完成,作业 i i i 有截止时间 d i d_i di ,当作业 i i i 在截止时间被执行完,则可获得 p i p_i pi 的收益。求最大收益。

思路:
我们选择用贪心算法来求解。
先将所有作业按照收益从大到小排序,然后按顺序遍历所有作业,把 最靠近每个作业的截止时间的空闲时间 分配给该作业,若无空闲时间则跳过该作业。

源代码:

//
//  main.cpp
//  MachineOperation
//
//  Created by 胡昱 on 2021/12/31.
//

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

// 作业结构体
struct Operation{
    int ddl;    // 截止时间
    int w;      // 收益
};

// 根据收益比较作业
int compareByW(const void* a, const void* b) {
    return -(int)(((Operation*)a)->w - ((Operation*)b)->w);
}

int main(int argc, const char * argv[]) {
    // 共T组测试数据
    int T;
    cin >> T;
    while((T--) > 0) {
        // 输入作业数量
        int N;
        cin >> N;
        
        // 创建并输入作业数组N
        Operation* ops = new Operation[N];
        int maxDDL = 0;     // 记录最大截止时间
        for(int ni = 0; ni < N; ++ni) {
            Operation op;
            cin >> op.ddl >> op.w;
            ops[ni] = op;
            if(op.ddl > maxDDL) {
                maxDDL = op.ddl;
            }
        }
        
        // 最大截止时间等于0的话说明没有活动可以被选择
        if(maxDDL == 0) {
            cout << 0 << endl;
            continue;
        }
        
        // 创建时间数组来记录每个时间是否被占用,并初始化
        int* busyTime = new int[maxDDL + 1];
        for(int ti = 0; ti <= maxDDL; ++ti) {
            busyTime[ti] = 0;
        }
        
        // 因为是贪心算法,所以我们按收益大小进行排序
        qsort(ops, N, sizeof(Operation), compareByW);
        
        // 初始化结果
        int result = 0;
        
        // 开始选择作业
        for(int opi = 0; opi < N; ++opi) {
            // 是否有空闲时间执行该作业
            bool hasFreeTime = false;
            
            // 从DDL开始往前寻找空闲时间
            int time = ops[opi].ddl;
            while(time > 0) {
                if(busyTime[time] == 0) {
                    hasFreeTime = true;
                    break;
                }
                else {
                    --time;
                }
            }
            
            // 判断是否执行该作业
            if(hasFreeTime) {
                // 设置改时间已被占用
                busyTime[time] = 1;
                
                // 增加收益
                result += ops[opi].w;
            }
        }
        
        // 输出结果并释放资源
        cout << result << endl;
        delete [] ops;
        delete [] busyTime;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值