01揹包問題思想是將將總數進行拆分,拆分紅每塊錢(每一個重量基數)。ios
算法實現是將每一個物體抽象爲一行,每一列爲總數的細分,再分別從物體自己的價格(重量)到總數循環,每一次都進行f[i]=max{f[i],f[i-v[j]]+v[i]*w[i]}(f[i]爲每一格的最大收益,v[i]爲物體價格/重量,w[i]爲物體價值) 的比較,這樣執行完每一行均可以刷新這個價格(重量)區間的最大收益算法
#include<iostream> #include<algorithm> using namespace std; int N, m; int sum[30010]; struct thing { int price; int grade; }things[30]; void input();//輸入函數 int main() { int i, j; input(); for (i = 1; i <= m; i++) for (j =N ; j >=things[i].price; j--)//*從後往前,這樣就不是被本行的計算覆蓋 sum[j] = max(sum[j], things[i].price*things[i].grade + sum[j - things[i].price]);//計算公式,將問題拆分紅每塊錢 cout << sum[N]; return 0; } void input() { cin >> N >> m; int i; for (i = 1; i <= m; i++) cin >> things[i].price >> things[i].grade; }
P1164 小A點菜spa
#include<iostream> using namespace std; const int N = 120; int v[N], f[N]; int main() { int n, m; int i, j; f[0] = 1;//當錢正好購買一個菜的時候狀況 cin >> n >> m; for (i = 1; i <= n; i++) cin >> v[i]; for (i = 1; i <= n; i++) for (j = m; j >= v[i]; j--) f[j] = f[j] + f[j - v[i]];//f[j]爲不買當前菜的狀況數,f[j-v[i]]爲買了當前菜用剩下的錢買其餘菜的狀況數 cout << f[m]; return 0; }
P1616 瘋狂的採藥code
#include<iostream> #include<algorithm> using namespace std; const int N = 10010; struct Med { int time, value; }med[N]; int sum[100010]; int main() { int T, M; int i, j; cin >> T >> M; for (i = 1; i <= M; i++) cin >> med[i].time >> med[i].value; for (i = 1; i <= M; i++) for (j = med[i].time; j <= T; j++)//只有這裏跟01揹包反過來,這樣能夠不斷更新每個狀態的最大價值,能夠作到一直取 sum[j] = max( sum[j],med[i].value + sum[j - med[i].time] ); cout << sum[T]; return 0; }