動態規劃經典最優子結構總結
(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】)