动态规划是算法里面的重点
这是我在b站up主–正月点灯笼的视频里面学会的一些动态规划知识
这是视频的连接,点击跳转,视频里有对本文章题目的详细图文讲解
该题目是一个临时工,在一个时间段里有8份工作可以选择,每份工作工作的时间不同,每份工作的报酬也不同,但工作时间可能重贴,重叠的工作不能选择,我们要找出最大受益的选择方案(最优解)。
因为视频有详细图文讲解,所以本文章没有图文,只用代码和文字描写。
我们对这八个工作内容进行编号1。。。。。8。
我们将该问题拆分为一个选与不选的问题,从后往前,如果我们非要选择第八个工作的话,那么我们就必须去掉和第八个工作时间有所重叠的工作,找到剩下还能选择的工作,此时,我们就有了两个选择
选择做第八个工作,就是第八个工作的报酬在加上还能选择的其他工作的最优解。
选择不做第八个工作,就是前七个工作的最优解。
再在这两个可能中找到最大报酬的那个就是我们要找的八个工作中的最优解了。
这就是该问题的求解方法,求解函数设为opt(i),设选择了第i个工作后还能选择的工作中最接近第i个工作的数组为prev:
opt[i]=max(opt[i-1],valuei+opt[prev[i]])
C++代码:
#include <iostream>
using namespace std;
int N=9;
typedef struct _meet{
int begin;
int end;
int value;
}meet;
class WorkMaxValue{
public:
meet *meets;
int n;
WorkMaxValue();
void solve();
};
WorkMaxValue::WorkMaxValue(){
n=N;
meets=new meet[n]{
{0,0,0},//因为将工作从1开始而数组从0开始,所以0,0,0用来占位
{1,4,5},
{3,5,1},
{0,6,8},
{4,7,4},
{3,8,6},
{5,9,3},
{6,10,2},
{8,11,4}
};
return;
}
void WorkMaxValue::solve(){
if(n==1)
cout<<meets[1].value;
int i,j;
int prev[N]={0};//表示非要选i这个临时工作的话,还能选的前面最接近时间的临时工作是什么
for(i=2;i<N;i++){//从第二个开始是因为第0个是用0,0,0来占位的,第一个没有前面的工作所以不能比较
for(j=i-1;j>=1;j--){
if(meets[i].begin==meets[j].end){//这里有问题,但在本题目中能够通过,应该是最接近的而不是刚好相连的
prev[i]=j;
break;
}
}
}
int opt[N]={0};//在前i个工作中,能赚的最大金额
for(i=1;i<N;i++){
if(prev[i]==0)
opt[i]=max(meets[i].value,opt[i-1]);
else
opt[i]=max(meets[i].value+opt[prev[i]],opt[i-1]);
}
for(i=1;i<N;i++)
cout<<opt[i]<<" ";
}
int main(){
WorkMaxValue WMV;
WMV.solve();
return 0;
}