【記憶化搜尋】01揹包
阿新 • • 發佈:2018-12-24
記憶化搜尋也是實現dp的一種,有時候可能比狀態轉移方程推過去複雜,但有時候因為是直接去搜索,反而降低了思維難度
就用01揹包來練練手(設c為容量,w為重量,v為價值)
- 記憶化搜尋是在搜尋的基礎上,進行優化,跳過開啟相同的子樹,從而避免大量的重複計算。因為在搜尋的時候可能會再次dfs到一個已經到過的點,而這個點又會再開啟一棵很大的子樹,這樣就會進行大量的重複計算,所以如果這個點訪問完畢,我們記錄下這個點的值,再次訪問時直接返回這個值,就不要再開啟這棵子樹
if(f[i][j] > 0) return f[i][j];
對於01揹包,有選和不選兩種轉移方式
採用直接搜尋(從i=1, j=c 開始搜尋)
對於f(i,j) 直接去搜索f(i+1,j)和f(i + 1,j - w[i])的值,再根據選和不選加上v[i]
由於開啟dfs發生在賦值之前,賦值是逆序的,在f(i,j)確定之前,f(i+1,j)和f(i+1,j-w[i])一定已經被確定好了,這樣狀態就可以被正確地轉移
還有些邊界條件,具體看程式碼
#include <algorithm>
#include <iostream>
#include <cstdio>
using namespace std;
#define debug(x) cerr << #x << "=" << x << endl;
const int MAXN = 1000 + 10;
int n,c,f[MAXN][MAXN],w[MAXN],v[MAXN];
int dfs(int i, int c) {
if(f[i][c]) return f[i][c];
if(i == n+1) return 0;
if(c >= w[i])
f[i][c] = max(dfs(i+1,c), dfs(i+1 ,c-w[i]) + v[i]);
else
f[i][c] = dfs(i+1,c);
return f[i][c];
}
int main() {
cin >> c >> n;
for(int i=1; i<=n; i++)
cin >> w[i] >> v[i];
cout << dfs(1,c);
return 0;
}