带时限的作业排序问题--贪心问题

问题描述

设有一个单机系统、无其它资源限制且每个作业运行相等时间,不妨假定每个作业运行1个单位时间。现有n(0<n<1000)个作业,每个作业都有一个截止期限di>0,di为整数,1<=i<=n。如果作业能够在截止期限之内完成,可获得pi>0的收益。问题要求得到一种作业调度方案,该方案给出作业的一个子集和该作业子集的一种排列,使得若按照这种排列次序调度作业运行,该子集中的每个作业都能如期完成,并且能够获得最大收益。

输入

第一行一个正整数,表示n的值,以下n行,每行三个整数,分别表示作业号i,收益pi,截止期限di。

输出

n个作业的一个最优子集。作业号从小到大输出,之间用一个空格分隔。

样例输入

4
1 100 2
2 10 1
3 15 2
4 27 1

样例输出

1 4

参考代码

#include<bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef pair<int, int>PII;
PII logs[100100];
int n;
int v[10010];
int p[10010];//收益
int d[10010];//截止期限
int d1[10010]; //跟随p[i]排序后的截止期限
int x[10010];//
int b[10010];
bool cmp(const pair<int,int> &p1,const pair<int,int> &p2)
{
	if(p1.first>p2.first)
		return true;
	else 
		return false;
}
int main(){
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>v[i]>>p[i]>>d[i];
	}
	for(int i=0;i<n;i++){
		logs[i].x=p[i];//按p[i]排序 100 27 15 10
		logs[i].y=d[i];//d[i]随之排序 
	}
	sort(logs,logs+n,cmp);
	for(int i=0;i<n;i++){
		d1[i]=logs[i].y;
	}
	for(int i=0;i<n;i++){//恢复标号 
		logs[i].x=p[i];
		logs[i].y=v[i];//1 4 3 2
	}
	sort(logs,logs+n,cmp);
	int k=0;
	x[0]=0;
	for(int j=1;j<n;j++){
		int r=k;
		while(r>=0&&d1[x[r]]>d1[j]&&d1[x[r]]>r+1){
			r--;//搜索作业j的插入位置 
		}
		if((r<0||d1[x[r]]<=d1[j])&&d1[j]>r+1){//若条件不满足,选下一个作业
			for(int i=k;i>=r+1;i--) x[i+1]=x[i];//将x[r]以后的作业后移
			x[r+1]=j;//将作业j插入r+1
			k++;
		} 
	}
	for(int i=0;i<=k;i++){
		b[i]=logs[x[i]].y;
	}
	sort(b,b+k+1);
	for(int i=0;i<=k;i++){
		cout<<b[i]<<" ";
	}
	return 0;
} 

在这里插入图片描述在这里插入图片描述

思路

  • 4
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值