AcWing 10. 有依賴的揹包問題
阿新 • • 發佈:2022-04-04
題目連結
https://www.acwing.com/problem/content/10/
題解
需要注意的點就是,f[u][j]實際上是優化過第第二維後的狀態表示,原狀態表示應該是f[u][i][j]:對於根結點u,考慮其前i個子樹,總體積不超過j的最大價值
dfs(root)的遞迴含義是:以root為根,考慮其所有子樹,總體積不超過max_V的最大價值。
AC程式碼
import java.util.*; public class Main { static int N = 110; static int[] v = new int[N], w = new int[N]; static int[] h = new int[N], e = new int[N], ne = new int[N]; static int[][] f = new int[N][N]; static int idx = 0; static int n, m; static { Arrays.fill(h, -1); } static void add(int a, int b) { e[idx] = b; ne[idx] = h[a]; h[a] = idx ++; } static void dfs(int u) { for (int j = v[u]; j <= m; j ++) f[u][j] = w[u]; // 優化了第二維,省略了i,對於實際上應該:是對於根結點u // 考慮其前i個子樹,總體積不超過j的最大價值 for (int i = h[u]; i != -1; i = ne[i]) { int son = e[i]; dfs(son); for (int j = m; j >= v[u]; j --) // 所以這裡要倒寫 // 考慮前i個子樹,給son_i這個子樹,k體積,其他j - k體積 for (int k = 0; k <= j - v[u]; k ++) { // 這裡的f[son][k],第二位是考慮了son的所有子樹的,f[son][son_sons][k] f[u][j] = Math.max(f[u][j], f[u][j - k] + f[son][k]); } } } public static void main(String[] args) { Scanner sc = new Scanner(System.in); n = sc.nextInt(); m = sc.nextInt(); int root = -1; for (int i = 1; i <= n; i ++) { int vi = sc.nextInt(), wi = sc.nextInt(), pi = sc.nextInt(); v[i] = vi; w[i] = wi; if (pi == -1) root = i; else { add(pi, i); } } dfs(root); System.out.println(f[root][m]); } }