題目有n個重量和價值為wi,vi的物品,從這些物品中挑選出總重量不超過m的物品,求所有可選方案中價值總和的最大值。
1<=n<=100
1<=wi,vi<=100
1<=w<=10000
輸入:n=4
(w,v)=,,,}
w=5輸出:
7(選擇0,1,3號物品)
//和子集、全排列很像 ,選還是不選
//用dfs解決
#include
using
namespace std;
//全域性不需要傳參
int w=
;//重量表
int v=
;//**表
int n=4;
int w=5;
int rec[5]
[6];
intdfs
(int i,
int ww)
//從i號物品開始選 ,ww為還可以裝物品重量
else
}int
main()
//出現了重疊子問題
//解決方法:記憶形遞迴,帶備忘錄
//rec增加速度很多
改進:增加記憶化搜尋,加快搜尋速度
int
dfs1
(int i,
int ww)
//從i號物品開始選 ,ww為還可以裝物品重量
else
//2.計算之後做儲存
rec[i]
[ww]
=ans;
return ans;
}
用excel找規律(dp問題要理解**),演算法根據填表邏輯寫;(w,v)找出變化的量:容量變化、物品範圍變化、**變化;
兩個自變數(包的容量,物品選哪些),乙個因變數(**)
畫出二維表
物品編號(當前編號以及之前的範圍)01
2345
(2,3)00
0333
3(1,2)10
2=max(要:2+0,不要:0)
3=max(要:2+0,不要:3)
5=max(2+3,3)
5=max(2+3,3)
5=max(2+3,3)
(3,4)20
235=(4+0,5)
6=(4+2,5)
7=(4+3,3)
(2,2)30
23=(2+0,3)
5=(2+3,5)
6=(2+3,6)
7=(2+5,7)
最右下角的單元格即為所求根據**寫出演算法如下:從歷史資料處理得出結果 :
我不要這個物品:找上方的單元格
要的話:本物品**+減去當前物品容量的上一行單元格對應的**
intdp(
)else
}//其他行
for(
int i=
1;i)else}}
return dp[n-1]
[w];
}//遞迴要等子問題結果
//dp不用等,直接用已有問題
intmain()
#include
#include
#include
#include
#include
using
namespace std;
intmax
(int a,
int b)
int f[
1001][
1001];
intmain()
for(
int i=
1;i<=n;i++
)memset
(f,0
,sizeof
(f))
;//把f陣列清零
//和上述演算法不同,邊界是從第一列考慮的
for(
int i=
1;i<=n;i++)}
cout<[v]<}return0;
}
小建議:希望把用dp演算法解決的問題的陣列名都改為dp
揹包問題 01揹包問題
n個物品,總體積是v,每個物品的體積的vi,每個物品的最大價值是wi,在不超過v的體積下求最大價值 eg揹包容積為 5 物品數量為 4 物品的體積分別為 物品的價值分別為 思路定義乙個二位陣列int f new int n 1 v 1 f i j 就表示在1 i個物品中選取體積小於v的情況的最大價值...
揹包問題 01揹包
有n件物品和乙個容量為v的揹包。第i件物品的重量是c i 價值是w i 求解將哪些物品裝入揹包可使價值總和最大。01揹包中的 01 就是一種物品只有1件,你可以選擇放進去揹包即1,也可以選擇不放入揹包中即0。include include using namespace std const int ...
揹包問題(01揹包)
1085 揹包問題 在n件物品取出若干件放在容量為w的揹包裡,每件物品的體積為w1,w2 wn wi為整數 與之相對應的價值為p1,p2 pn pi為整數 求揹包能夠容納的最大價值。input 第1行,2個整數,n和w中間用空格隔開。n為物品的數量,w為揹包的容量。1 n 100,1 w 10000...