动态规划

动态规划是通过组合子问题的解来求解原问题。与分治方法不同的是,动态规划应用于子问题重叠的情况,即不同的子问题具有公共的子子问题。

这种方法一般需要恰当定义子问题的规模的概念,使得任何子问题的求解都只依赖于更小的子问题的求解。因而,我们可以将子问题按照规模排序,按照有小到大的顺序进行求解。当求解某个子问题时,它所依赖的那些更小的子问题都已经求解完毕,结果已经保存。每个子问题只需要求解一次,当我们求解它时,它的所有前提子问题都已经求解完成。

经典问题:(通性:对每一个子问题都进行计算,算完子问题就得到答案,时间复杂度 = 问题大小 * 最简问题的时间复杂度 一般是 O(n))

最小上升子序列问题

/*
  没有实现搜索
*/
#include<stdio.h>
#define MAX 1001
#define max(a,b) a>b?a:b 
int process(int *mermory,int *data,int n);
int main(){
	int i,n,data[MAX],mermory[MAX]={0};
	mermory[1]=1;
	scanf("%d",&n);
	for(i=1;i<=n;i++)
		scanf("%d",&data[i]);
	int result = process(mermory,data,n);
	printf("these is %d",result);	
	return 0;
}
int process(int *mermory,int *data,int n){
	int i,j,temp;
	for(i=1;i<=n;i++){
		temp=1;
		for(j=1;j<i;j++){
			if(data[i] > data[j])
				temp=max(temp,mermory[j]+1);
		}
		mermory[i]=temp;
	}
	return mermory[n];
} 

钢条分割问题

/*
	钢条分割问题;分割钢管的长度是从1开始的到N的长度
	val装的是每段长度对应下的价值 
	(动态规划 )
*/
#include<stdio.h>
#define MAX 101
#define MAXN 100001
int process(int *momery,int *val,int length,int n);
int max(int a,int b){
	return a>b?a:b;
}
int main(){
	int n,len,i,val[MAX]={0},momery[MAXN]={0};
	scanf("%d",&n);
	for(i=1;i<=n;i++){
		scanf("%d",&val[i]);
	}
	scanf("%d",&len);
	printf("the process is :\n");
	int result = process(momery,val,len,n);
	printf("\n%d\n",result);
	return 0;
}
int process(int *momery,int *val,int length,int n){
	int i,j,temp,k,solve[MAX]={0};
	for(i=1;i<=length;i++){
		temp=-1;
		for(j=1;j<=i;j++){
			/**/
			if(j <= n && temp < momery[i-j]+val[j]){//此时的 j 就是截段的长度 
				temp = momery[i-j]+val[j];//用于搜索合适的切断方式 
				solve[i]=j;
			}
			/**/
			/*
				如果不用找出具体的解决方法
				则可以用底下这个代码
				temp = max(temp,momery[i-j]+val[j]) 
			*/
		}
		momery[i]=temp; 
	}
	int len=length;
	while(len > 0)//解决方法的输出 
	{
		printf("%d ",solve[len]);//solve 里面装的是每次子段钢管的截断长度, 
		len=len - solve[len];//每次将长度减掉解决方法,就是模拟截钢管的过程 
	}
	printf("\n"); 
	return momery[length];
}
	

背包问题

动态规划原理
虽然已经用动态规划方法解决了上面两个问题,但是大家可能还跟我一样并不知道什么时候要用到动态规划。总结一下上面的斐波拉契数列和钢条切割问题,发现两个问题都涉及到了重叠子问题,和最优子结构。

①最优子结构

用动态规划求解最优化问题的第一步就是刻画最优解的结构,如果一个问题的解结构包含其子问题的最优解,就称此问题具有最优子结构性质。因此,某个问题是否适合应用动态规划算法,它是否具有最优子结构性质是一个很好的线索。使用动态规划算法时,用子问题的最优解来构造原问题的最优解。因此必须考查最优解中用到的所有子问题。

②重叠子问题

在斐波拉契数列和钢条切割结构图中,可以看到大量的重叠子问题,比如说在求fib(6)的时候,fib(2)被调用了5次,在求cut(4)的时候cut(0)被调用了4次。如果使用递归算法的时候会反复的求解相同的子问题,不停的调用函数,而不是生成新的子问题。如果递归算法反复求解相同的子问题,就称为具有重叠子问题(overlapping subproblems)性质。在动态规划算法中使用数组来保存子问题的解,这样子问题多次求解的时候可以直接查表不用调用函数递归。
原文链接:https://blog.csdn.net/u013309870/article/details/75193592

优点

便于寻找到最优解的具体的步骤(回溯?)

从结果上看,如果最优解的方法每一步之间的顺序改变会影响其是否为最优解

那么该问题是不可用动态规划解决的

posted @ 2022-11-10 16:59  MITE's_BKY  阅读(44)  评论(0)    收藏  举报