一、動態規劃
狀態轉移方程:
從前往後:
if(j>=w[i])
m[i][j]=max(m[i-1][j],m[i-1][j-w[i]]+v[i]);
else
m[i][j]=m[i-1][j];
從後往前:
if(j>=w[i])
m[i][j]=max(m[i+1][j],m[i+1][j-w[i]]+v[i]);
else
m[i][j]=m[i+1][j];
演算法:
從前往後:
for(int i=1;i<=n;i++)
for(int j=1;j<=c;j++)
else//這裡沒有考慮j<0的情況,因為演算法中j取不到
}從後往前:
for(int i=n;i>=1;i--)
for(int j=1;j<=c;j++)
else
}
例子:
例:0-1揹包問題。在使用動態規劃演算法求解0-1揹包問題時,使用二維陣列m[i][j]儲存揹包剩餘容量為j,可選物品為i、i+1、……、n時0-1揹包問題的最優值。繪製
重量陣列w = ,
價值陣列v = ,
揹包容量c = 12時對應的m[i][j]陣列。(從前往後)01
2345
6789
1011121
0008
8888
8888
2000
881010
1010
1818183
0668
8141416
1618
182440
6699
1414
1717
1919245
0669
9141417
1719
212462
68911
1416
1719
1921
24例題** :
#include#include#include#define n 20
using namespace std;
int main()
,v[n]=;
int m[n][n];
memset(m,0,sizeof(m));
int n=6,c=12; //n,c均要小於n
for(int i=1;i<=n;i++)
for(int j=1;j<=c;j++)
else
}cout<=1;i--)
for(int j=1;j<=c;j++)
else
}cout《二、回溯法
1進入左子樹條件:cw+w[i]<=c //cw為當前重量
2進入右子樹條件(減枝函式):cp+r>bestp //cp為當前價值,bestp為當前最優價值,r為當前剩餘物品價值總和。cp+r由函式 bound計算。
3需要先將物品按單位重量價值從大到小排序,按序進入左子樹;進入右子樹時,由函式bound計算當前節點上界,只有其上界大於當前最優價值bestp時,才進入右子樹,否則減去。
演算法:void backtrack(int i)
if(cw+w[i]<=c) //進入左子樹
if(bound(i+1)>bestp) //進入右子樹 }
int bound(int i) //計算上界
if(i<=n)//裝滿揹包
return b;
}
例子**:
#include#define n 20
using namespace std;
int w[n]=,v[n]=;
int n=6,c=12;
int cp=0,cw=0,bestp=0;
int bound(int i) //計算上界
if(i<=n)//裝滿揹包
return b;
}void backtrack(int i)
if(cw+w[i]<=c) //進入左子樹
if(bound(i+1)>bestp) //進入右子樹 }
int main()
0 1揹包問題 動態規劃法
問題描述 給定n種物品和一揹包。物品i的重量是w i 其價值為v i 揹包的容量為c。問應如何選擇裝入揹包的物品,使得裝入揹包中物品的總價值最大?分析 對於一種物品,要麼裝入揹包,要麼不裝。所以對於一種物品的裝入狀態可以取0和1。設物品i的裝入狀態為xi,xi 0,1 此問題稱為0 1揹包問題。資料...
0 1揹包問題 動態規劃法
問題描述 給定n種物品和一揹包。物品i的重量是w i 其價值為v i 揹包的容量為c。問應如何選擇裝入揹包的物品,使得裝入揹包中物品的總價值最大?分析 對於一種物品,要麼裝入揹包,要麼不裝。所以對於一種物品的裝入狀態可以取0和1。設物品i的裝入狀態為xi,xi 0,1 此問題稱為0 1揹包問題。資料...
動態規劃法 01揹包問題
一 幾個概念 最優化問題 有 n個輸入。它的解由這 n個輸入的乙個子集組成,這個子集必須滿足某些事先給定的條件。這些條件稱為約束條件。滿足約束條件的解稱為問題的可行解。滿足約束條件的可行解可能不止乙個,為了衡量這些可行解的優劣,事先給出一定的標準,這些標準通常以函式的形式給出。這些標準函式稱為目標函...