不妨先用最樸素的方法,針對每個物品是否放入揹包進行搜尋:
// 輸入
int n, w;
int w[max_n], v[max_n];
// 從第 i 個物品開始挑選總重小於 j 的部分
int rec(int i, int j) else if (j < w[i]) else
return res;
}void solve()
只不過,這種方法的搜尋深度是
int dp[max_n + 1][max_w + 1]; // 記憶化陣列
int rec(int i, int j)
int res;
if (i == n) else if (j < w[i]) else
// 將結果儲存在陣列中
return dp[i][j] = res;
}void solve()
對於同樣的引數,只會在第一次被呼叫到時執行遞迴部分,第二次之後都會直接返回。引數的組合不過記憶化搜尋。
如果對記憶化搜尋還不是很熟練的話,可以寫成窮竭搜尋的寫法:
// 目前選擇的物品價值總和是 sum,從第 i 個物品之後的物品中挑選重量總和小於 j 的物品
int rec(int i, int j, int sum) else if (j < w[i]) else
return res;
}
在需要剪枝的情況下,可能會像這樣把各種引數都寫在函式上,但在這種下會讓記憶化搜尋難以實現,需要注意。
接下來,我們來仔細研究一下前面的演算法利用到的這個記憶化陣列。記
這樣不用寫遞迴函式,直接利用遞推式將各項的值計算出來,簡單的二重迴圈也能解決這一問題。
int dp[max_n + 1][max_w + 1]; // dp 陣列
void solve() else }}
printf("%d\n", dp[0][w]);
}
這個演算法的複雜度與前面的相同,也是動態規劃法,也就是常說 三種簡單揹包問題模板 01揹包 完全揹包 多重揹包
概念 給定n種物品的價值和重量,每種物品最多只能取一次。求出當揹包容量為m時能夠裝下的最大價值 一維的寫法,dp陣列代表的是當前狀態能夠放下的最大價值 for int i 0 i w i j dp j max dp j dp j w i v i 對於第i件物品,可以放或不放。不放 dp j dp j...
混合三種揹包問題
問題 如果將01揹包 完全揹包 多重揹包混合起來。也就是說,有的物品只可以取一次 01揹包 有的物品可以取無限次 完全揹包 有的物品可以取的次數有乙個上限 多重揹包 應該怎麼求解呢?01揹包與完全揹包的混合 考慮到在01揹包和完全揹包中最後給出的偽 只有一處不同,故如果只有兩類物品 一類物品只能取一...
混合三種揹包問題
問題 如果將01揹包 完全揹包 多重揹包混合起來。也就是說,有的物品只可以取一次 01揹包 有的物品可以取無限次 完全揹包 有的物品可以取的次數有乙個上限 多重揹包 應該怎麼求解呢?01揹包與完全揹包的混合 考慮到在01揹包和完全揹包中最後給出的偽 只有一處不同,故如果只有兩類物品 一類物品只能取一...