动态规划
动态规划是通过组合子问题的解来求解原问题。与分治方法不同的是,动态规划应用于子问题重叠的情况,即不同的子问题具有公共的子子问题。
这种方法一般需要恰当定义子问题的规模的概念,使得任何子问题的求解都只依赖于更小的子问题的求解。因而,我们可以将子问题按照规模排序,按照有小到大的顺序进行求解。当求解某个子问题时,它所依赖的那些更小的子问题都已经求解完毕,结果已经保存。每个子问题只需要求解一次,当我们求解它时,它的所有前提子问题都已经求解完成。
经典问题:(通性:对每一个子问题都进行计算,算完子问题就得到答案,时间复杂度 = 问题大小 * 最简问题的时间复杂度 一般是 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
优点
便于寻找到最优解的具体的步骤(回溯?)
从结果上看,如果最优解的方法每一步之间的顺序改变会影响其是否为最优解
那么该问题是不可用动态规划解决的

浙公网安备 33010602011771号