算法----动态规划(1)

动态规划思想

把问题拆分成若干个子问题,类似递归(分治),但是动规多用于处理最优解,有重叠子问题的问题,因为动态规划对于重叠子问题不会反复计算,会创建一张表将之前计算过的子问题答案直接保存,避免了重复计算,加快计算速度

练习1:有8个任务,每个任务完成需要一定的时间,完成之后就会有相应的报酬(图上的红色字段),但是任务有时间点限制,比如第一个任务在1点到4点。。。。任务之间不能并发,那么一个人做那几个任务可以获取到最高的报酬?

这个思想我们就用动态规划,我们对于某一个任务我们采取选与不选,看选的话获取的报酬大还是不选获取的报酬大,我们设定一个表达式OPT(i),表示到第i个任务的最优解。

比如:我们OPT(8)就有两种结果,一种是选择了8号任务,那么他就不能选择6,7任务;若不选择8号,那么最优值就是OPT(7),所以这个问题的递归式就是

                           选择:vi + OPT(i-x);     //i-x是距离i之前最近的一个可以选择的任务,vi表示i任务的报酬

OPT(i)=max {

                            不选择:OPT(i-1);

 我们可以将某一个任务执行的话,他前边最近可以执行的任务号列一个表,以及我们看一下展开图

可以看出,我们将这个展开图中出现了重叠子问题,比如这个OPT(5),那么我们就可以先算出每一个任务对应的OPT,列出这张表,表填完的时候答案也就自然揭晓了(到最后一个任务)。

                     

这就是这道题的思想,那么上代码

#include<iostream>
#include<map>
#include<vector>
using namespace std;
int main()
{
	int val[8]={5,1,8,4,6,3,2,4};  //每一个任务的报酬 
	int arr[8][2]={1,4,3,5,0,6,4,7,3,8,5,9,6,10,8,11};  //存放每一个任务的开始与结束点 
	vector<int> vec(8);    //存储每一个任务距离他最近的前面的可以同时执行的任务下标 
	int i=0;
	int j=0;
	for(;i<8;i++)
	{
		for(j=i-1;j>=0;j--)
		{
			if(arr[j][1]<=arr[i][0])
			{
				vec[i]=j;
				break;		
			}
		} 
		if(j<0)
			vec[i]=-1;
	}
	vector<int> sumval(8);
	sumval[0]=val[0];
	for(i=1;i<8;i++)
	{
		if(vec[i]!=-1)
			sumval[i]=max(sumval[i-1],val[i]+sumval[vec[i]]);
		else
			sumval[i]=max(sumval[i-1],val[i]);
	}
	cout<<sumval[7]<<endl;
} 

对于递归版当然很好写了

int GetSumVal(int i)
{
	if(i==0) return val[0];
	else 
	{
		if(vec[i]==-1)
			return max(GetSumVal(i-1),GetSumVal(vec[i]));
		return max(GetSumVal(i-1),GetSumVal(vec[i])+val[i]);
	}	
}
int main()
{
    cout<<GetSumVal(7)<<endl;
}

以上就是动态规划的大致思想,就是杜绝这种重复的子问题多次计算!!!用表记录,表填完的时候答案也就出来了

猜你喜欢

转载自blog.csdn.net/Eunice_fan1207/article/details/89473532
今日推荐