零件最大加工报酬问题

用机器加工一批零件。每一个零件加工完可获得一定的加工报酬,并有加工时间要求:零件加工必须从某一时刻开始,到某一时刻结束,一次性连续加工完。
零件的加工时间要求可能有冲突,但机器只有一台,在某个时刻,只能加工一个零件。一个零件开始时间和另一个零件结束时间相同不算冲突。
请实现如下需求:在一批零件中,合理选择零件加工,输出满足上述条件的
1)最大加工报酬。
2)最优零件加工序列:能获得最大加工报酬的所有零件加工序列(可能有多组序列)

说明: 
每一个零件的信息包括:零件编号,零件加工报酬,加工开始时间,加工结束时间。每个零件的零件编号不能重复。 
    示例:
        零件信息——
                  零件编号 零件加工报酬 加工开始时间 加工结束时间
                      1         10           1            2
                      2         15           5            6
                      3         20           4            6
                      4         15           1            5
                      5         20           4            6

计算结果: 
1)最大加工报酬:30

2)最优零件加工序列: 有三个,分别是{1,3}、{1,5}、 {4,2}

解法:

typedef struct product
{
int id;
int reward;
int start_time;
int end_time;
}Product;

Product P[N];

本题可用动态规划来解,首先将各个零件依据零件的加工结束时间从大到小进行排序,然后定义一个数组r[N],其中r[i]为到第i个为止的最大报酬,

则r[i]=max{r[j]+P[i].reward,0<=j<i,且第i个零件的加工时间和第j个零件的加工时间不重合},最后的最大报酬为max{r[i],0<=i<n},本题与数组的最长递增子序列有几分相似之处。

为了求得最优零件加工序列需要用数组pre[N]保存满足r[i]=max{r[j]+P[i].reward,0<=j<i,且第i个零件的加工时间和第j个零件的加工时间不重合} 条件的零件。最后遍历r[N]一遍,找出满足r[i]==maxreward的零件的id并根据pre[N]数组,打印出最优零件加工序列。

具体代码如下:

#include<iostream>
#include<algorithm>
using namespace std;
typedef struct product//零件信息
{
	int id;
	int reward;
	int start_time;
	int end_time;
}Product;
bool comp(Product p1,Product p2);//零件排序依据
bool overlap(Product p1,Product p2);//判段区间是否交叉
void max_reward(Product *P,int n);//求最大报酬
void print_path(int m,int *pre,Product *P);//打印最优序列
int main()
{
	int n;
	cin>>n;
	Product *P=new Product[n];
	int i;
	for(i=0;i<n;i++)
		cin>>P[i].id>>P[i].reward>>P[i].start_time>>P[i].end_time;
	sort(P,P+n,comp);
	max_reward(P,n);
	delete []P;
	return 0;
}
bool comp(Product p1,Product p2)
{
	return p1.end_time<p2.end_time;
}
bool overlap(Product p1,Product p2)
{
	if(p1.end_time <=p2.start_time||p2.end_time<=p1.start_time)
		return false;
	return true;
}
void max_reward(Product *P,int n)
{
	if(P==NULL||n<=0)
		return;
	int *r=new int[n];
	int *pre=new int[n];
	int i,j;
	for(i=0;i<n;i++)
		pre[i]=-1;
	for(i=0;i<n;i++)
	{
		r[i]=P[i].reward;
		for(j=0;j<i;j++)
		{
			if(!overlap(P[i],P[j])&&(r[i]<r[j]+P[i].reward))
			{
				r[i]=r[j]+P[i].reward;
				pre[i]=j;
			}
		}
	}
	int maxreward=0x8fffffff;
	for(i=0;i<n;i++)
	{
		if(r[i]>maxreward)
			maxreward=r[i];
	}
	cout<<"The maximum reward is "<<maxreward<<endl;
	int k=1;
	for(i=0;i<n;i++)
	{
		if(r[i]==maxreward)
		{
			
			cout<<k++<<" : ";
			print_path(i,pre,P);
			cout<<endl;
		}
	}
	delete []r;
	delete []pre;
}
void print_path(int m,int *pre,Product *P)
{
	if(m<0||pre==NULL||P==NULL)
		return;
	if(m==0)
	{
		cout<<P[m].id<<" ";
		return;
	}
	print_path(pre[m],pre,P);
	cout<<P[m].id<<" ";
}

时间复杂度为O(n^2),空间复杂度为O(n);

原文地址:https://www.cnblogs.com/james1207/p/3303875.html