【算法设计】带有期限的作业排序(贪心算法)

目录

问题描述:

测试数据:

函数实现:

数据存储:

算法描述:

 完整代码:


问题描述:

已知:

        n个作业,每个作业都有一个截止期限di,当且仅当作业i在它的期限截止以前被完成时,可获得pi的效益。

求:

        可行解集合J


测试数据:

n=4,(p1,p2,p3,p4)=(100,20,15,10);

          (d1,d2,d3,d4)=(2,1,3,1)。

可行解:J=(2,1,3),p=100+20+15。

注:这里默认作业是按照效益p1>=p2>=p3……

        如果效益随机输入,考虑使用结构体数组


函数实现:

void JS ( int D[ ], int J[ ], int n, int &k );

数据存储:

        1)D(1:n)是期限值【D(0)=0】,效益p集合一样,并且是非增次序;

        2)J(i)是最优解中的第 i 个作业【J(0)=0】;

        3)最终 J满足D[J(i)]<=D[J(i+1)];

        4)k 为J中可行解的个数。

算法描述:

        1)作业 1 放入J[1];

        2)从第2个作业开始,

                i)先根据期限大小,寻找作业 i 在 J 中的位置,D[J(i)]和 J 中已有作业的期限比较 d[J[r]] > d[i] && d[J[r]] != r 。从J的最后一个开始比较,i期限小则r--,使得J中期限不为增序。

                ii)符合条件则 J(r+1:k)中作业序号,向后平移,空出J[r+1],插入作业 i,k加一。


 完整代码:

#include<iostream>
using namespace std;

#define N 5

void JS(int d[], int J[], int n, int &k)
{
	int r;
	k = 1; J[1] = 1;//计入作业1
	for (int i = 2; i <= N; i++)
	{
		r = k;
		while (d[J[r]] > d[i] && d[J[r]] != r)//寻找位置&&
		{
			r = r - 1;
		}
		if (d[J[r]] <= d[i] && d[i] > r)//d[i]>r表示在期限内
		{
			for (int j = k; j > r; j--)
			{
				J[j + 1] = J[1];//向后平移
			}
			J[r + 1] = i;
			k++;
		}
	}
}

int main()
{
	int d[N], p[N], J[N] = { 0 };
	//初始化

	cout << N-1 << "个期限:" << endl;
	for (int i = 1; i < N; i++)
	{
		cin >> d[i];
	}

	cout << N-1 << "个效益(降序):" << endl;//降序
	for (int i = 1; i < N; i++)
	{
		cin >> p[i];
	}
	d[0] = p[0] = 0;//d(1:n)是期限值,p(1:n)并且是降序

	int k;//个数
	JS(d, J, N, k);
	for (int i = 1; i <= k; i++)
	{
		cout << "作业编号:" << J[i] << "  作业效益:" << p[J[i]] 
			<< "  作业期限:" << d[J[i]] << endl;
	}
	cout <<"可行解个数" << k << endl;
	return 0;
}

(小声说:就是按照书上(《计算机算法基础》)的伪代码写的)

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值