问题描述
设有一个单机系统、无其它资源限制且每个作业运行相等时间,不妨假定每个作业运行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;
}