贪心法-带有限期的作业排序

问题描述
–假定在一台机器上处理n个作业,每个作业均可在单位时间内完成;同时每个作业i都有一个截至期限di>0,当且仅当作业i在其截至期限以前被完成时,则获得pi>0的效益。
–问题: 求这n个作业的一个子集J,其中的所有作业都可在其截至期限内完成。——J是问题的一个可行解。
–可行解J中的所有作业的效益之和是 ,具有最大效益值的可行解是该问题的最优解。

目标函数:


–约束条件:
所有的作业都应在其期限之前完成
–分析
如果所有的作业期限“足够宽松” ,而使得多有作业都能在其期限之内完成,则显然可以获得当前最大效益值;
否则,将有作业无法完成——决策应该执行哪些作业,以获得最大可能的效益值。

n=4,(p1,p2,p3,p4)=(100,10,15,20)和(d1,d2,d3,d4)=(2,1,2,1)。可行解如下表所示:


问题的最优解是⑦。所允许的处理次序是:先处理作业4再处理作业1。

量度标准:
下一个要计入的作业将是使得在满足所产生的J是一个可行解的限制条件下让 得到最大增加的作业。
处理规则:
按pi的非增次序来考虑这些作业。

procedure JS(D,J,n,k)
//D(1),…,D(n)是期限值。n≥1。作业已按p1≥p2≥…≥pn的顺序排序。J(i)是最优解中的第i个作业,1≤i≤k。终止时, D(J(i))≤D(J(i+1)), 1≤i<k//
integer D(0:n),J(0:n), i, k, n, r
D(0)←J(0)←0 //初始化//
k←1;J(1)←1 //计入作业1//
for i←2 to n do //按p的非增次序考虑作业。找i的位置并检查插入的可行性//
r←k
while D(J(r))>D(i) and D(J(r)) ≠r do r←r-1 repeat
if D(J(r))≤D(i) and D(i)>r then //把i插入到J中//
for i←k to r+1 by -1 do
J(i+1) ←J(i) //将插入点的作业后移一位//
repeat
J(r+1) ←i;k←k+1
endif
repeat
end JS

#include <iostream>

using namespace std;

/*D(1),…,D(n)是期限值。n≥1。作业已按p1≥p2≥…≥pn的顺序排序。
J(i)是最优解中的第i个作业,1≤i≤k。
终止时, D(J(i))≤D(J(i+1)), 1≤i<k
*/
void JS(int d[], int J[], int n, int &k)
{
    int i,j,r;
    d[0] = J[0] = 0;
    k = 1;
    J[1] = 1;
    for(i=2; i<=n; i++)
    {
        r = k;
        while(d[J[r]] > d[i] && d[J[r]] != r)
            r--;
        if(d[J[r]] <= d[i] && d[i]>r)
        {
            for(j=k; j>r; j--)
                J[i+1] = J[i];
            J[r+1] = i;
            k++;
        }
    }
}
int main()
{
    int d[5] = {0,2,1,2,1};
    int p[5] = {0,100,20,15,10};
    int J[5] = {0};
    int k;
    JS(d,J,4,k);
    for(int i=1; i<=k; i++)
        printf("%d-%d-%d  ", p[J[i]], d[J[i]], J[i]);
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值