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

(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;

shortest=inf;
moneyLeft=inf;
number=inf;
while(1){
	for(int z=0;z<A;z++)
	for(int x=0;x<N;x++){
		if(dp[z][x]<number){
			shortest=z;
			moneyLeft=x;
			number=dp[z][x];
		}
	}
	if(shortest==inf)break;
	for(int i=0;i<N;i++){
	if(ifVisited[i]==false&&g[shortest][i]!=0){
		if(moneyLeft>=money[i]&&g[shortest][i]+dp[shortest][moneyLeft]>dp[i][moneyLeft-money[i]]){
			dp[i][monetLeft-money[i]]=dp[shortest][moneyLeft]+g[shortest][i];
		}
	 }
   }
}
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】

__int64 number;
//初始化a数组 
for(int i=1;i<m;i++){
	a[i][i]=number%10;
	number/=10;
} 
for(int i=1;i<m;i++){
	for(int j=i+1;j<=m;j++){
		a[i][j]=a[i][j-1]*10+a[j][j];
	}
}
//进行规划
初始化dp后: 
for(int j=1;j<=n;j++){
	for(int i=j;i<=m;i++){
		for(int k=1;k<=i;k++){
			dp[i][j]=max(dp[i][j],dp[k][j-1]*a[k+1][j]);
		}
	}
} 

(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】)

    原文作者:动态规划
    原文地址: https://blog.csdn.net/lwtdzh999/article/details/51476566
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞