动态规划经典最优子结构总结

转载自:https://blog.csdn.net/lwtdzh999/article/details/51476566

(1)0-1背包:

如果有一个背包,总载重量为Wt,有n个物品,每个物品重Wi,每个物品价值Ci,那么如何装才能让这个包里面东西的价值最高?

dp[i][j]为前i个物品当中选择装进一个载重量为j的包里最大价值,则:

初始化:dp【0】【x】=0;for i=0-》n;j=0-》Wt

dp[i][j]的值为:dp[i-1][j](第i个物品不装进包里),dp[i-1][j-Wi]+Ci(第i个物品装进包里)的较大者。


(2)有代价的最短路径(动态规划和dijkstra混合使用):

寻求点1到点A之间的最短路,但是每到一个点就会消耗一点钱,这个值用money【i】来表示,钱不够路不通,初始有钱N。

dp【i】【j】为走到第i个点,还剩j钱的最短路径,则:

初始化dp【x】【y】=inf;dp【1】【N-money[1]】=0;ifvisited[x][y]=false;ifVisited[1][N-money[1]]=true;

[cpp]  view plain  copy
  1. shortest=inf;  
  2. moneyLeft=inf;  
  3. number=inf;  
  4. while(1){  
  5.     for(int z=0;z<A;z++)  
  6.     for(int x=0;x<N;x++){  
  7.         if(dp[z][x]<number){  
  8.             shortest=z;  
  9.             moneyLeft=x;  
  10.             number=dp[z][x];  
  11.         }  
  12.     }  
  13.     if(shortest==inf)break;  
  14.     for(int i=0;i<N;i++){  
  15.     if(ifVisited[i]==false&&g[shortest][i]!=0){  
  16.         if(moneyLeft>=money[i]&&g[shortest][i]+dp[shortest][moneyLeft]>dp[i][moneyLeft-money[i]]){  
  17.             dp[i][monetLeft-money[i]]=dp[shortest][moneyLeft]+g[shortest][i];  
  18.         }  
  19.      }  
  20.    }  
  21. }  
  22. result=max(dp[A][x]);  


(3)划分DP:

一个m位数,将其分成n部分,要求这n部分乘积最大,求分法。

规定a【i】【j】代表从第i位到j位这个数

并且,dp【i】【j】代表前i个数,分成k部分的最大积

那么,dp【i】【j】=dp【x】【k-1】*a【x+1】【j】的最大值,x从0到j-1

初始化的时候,需要把dp【x】【1】初始化为a【1】【x】

[cpp]  view plain  copy
  1. __int64 number;  
  2. //初始化a数组   
  3. for(int i=1;i<m;i++){  
  4.     a[i][i]=number%10;  
  5.     number/=10;  
  6. }   
  7. for(int i=1;i<m;i++){  
  8.     for(int j=i+1;j<=m;j++){  
  9.         a[i][j]=a[i][j-1]*10+a[j][j];  
  10.     }  
  11. }  
  12. //进行规划  
  13. 初始化dp后:   
  14. for(int j=1;j<=n;j++){  
  15.     for(int i=j;i<=m;i++){  
  16.         for(int k=1;k<=i;k++){  
  17.             dp[i][j]=max(dp[i][j],dp[k][j-1]*a[k+1][j]);  
  18.         }  
  19.     }  
  20. }   


(4)凑数

假设有几种整数:1,2,4。。。。。。请你用这些数凑一个整数N,要求用的数的数量最少,每种数可以多次使用

dp【i】代表凑数字i所需要用到的最小数量,那么

dp【i】=dp【i-1】到dp【i-2】到dp【i-4】的最小值加1.


(5)装配线调度。

有两个装配线,1号,2号,每个线有N个装配流程,一个产品要生产,必须走完这N个流程,但是每个流程要在1号或2号线装配是都可以的,每个流程所需时间为Cij,产品每进入一个其他的装配线(一开始不在装配线上,进入也算进入其他的装配线),需要消耗的时间为TIMEij,i代表第i条线,j代表第j个流程,求走完全部装配线最小时间。

dp【i】【j】代表在第i条线完成第j个流程所需最小时间。

则dp【1】【j】=min(dp【1】【j-1】+C1j,dp【2】【j-1】+TIME1j+C1j)


(6)序列S和T之间的距离定义:删除,修改,增加一个字符距离+1,最小的距离就是ST之间的距离,求ST之间最小距离:

dp【i】【j】代表S前i个T前j个的最小距离

则dp【i】【j】=min(dp【i-1】【j-1】+(s[i]==t[j])?0:1,dp【i-1】【j】+1,dp【i】【j-1】+1)


(7)最长公共子序列

当i==j dp【i】【j】=dp【i-1】【j-1】+1

如果i!=j,则dp【i】【j】=max(dp【i】【j-1】,dp【i-1】【j】)

回溯法求子序列:

while(unfinished){

if(s[i]=t[j]) push(s[i]); i--;j--;

else if(dp[i-1][j]大) i--,否则j--;

}


(8)最大子序列

dp【i】=(dp【i-1】>0?)dp【i-1】+string【i】:string【i】


(9)最长递增子序列

dp【k】代表前k个数字的最长,包含k

如果number【k】>number【k-1】,则dp【k】=dp【k+1】+number【k】

否则,向前寻找到第倒数第一个比k小的,比如是第A个,则dp【k】=max(dp【A】+number【k】)



  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值