通向自由的钥匙被放n个房间里,这n个房间由n-1条走廊连接。但是每个房间里都有特别的保护魔法,在它的作用下,我无法通过这个房间,也无法取得其中的钥匙。虽然我可以通过消耗能量来破坏房间里的魔法,但是我的能量是有限的。那么,如果我最先站在1号房间(1号房间的保护魔法依然是有效的,也就是,如果不耗费能量,我无法通过1号房间,也无法取得房间中的钥匙),如果我拥有的能量为P,我最多能取得多少钥匙?
输入数据
第一行包含两个非负整数,第一个为N,第二个为P。
接下来n行,按1~n的顺序描述了每个房间。第i+1行包含两个非负整数cost和keys,分别为第i件房取消魔法需要耗费的能量和房间内钥匙的数量。
接下来n-1行,每行两个非负整数x,y,表示x号房间和y号是连通的。
输出数据
一行一个整数,表示取得钥匙的最大值。
样例
输入:key.in
5 5
1 2
1 1
1 1
2 3
3 4
1 2
1 3
2 4
2 5
输出: key.out
7
一道树形dp基础题。
dfs后,两层循环都要倒着枚举。第一层循环是因为分组背包要倒着,第二层循环是因为有c = 0的情况。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cctype> 8 #include<vector> 9 #include<stack> 10 #include<queue> 11 using namespace std; 12 #define enter puts("") 13 #define space putchar(' ') 14 #define Mem(a, x) memset(a, x, sizeof(a)) 15 #define rg register 16 typedef long long ll; 17 typedef double db; 18 const int INF = 0x3f3f3f3f; 19 const db eps = 1e-8; 20 const int maxn = 105; 21 inline ll read() 22 { 23 ll ans = 0; 24 char ch = getchar(), last = ' '; 25 while(!isdigit(ch)) last = ch, ch = getchar(); 26 while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar(); 27 if(last == '-') ans = -ans; 28 return ans; 29 } 30 inline void write(ll x) 31 { 32 if(x < 0) x = -x, putchar('-'); 33 if(x >= 10) write(x / 10); 34 putchar(x % 10 + '0'); 35 } 36 void MYFILE() 37 { 38 #ifndef mrclr 39 freopen("key.in", "r", stdin); 40 freopen("key.out", "w", stdout); 41 #endif 42 } 43 44 int n, p; 45 int c[maxn], k[maxn]; 46 struct Edge 47 { 48 int nxt, to; 49 }e[maxn << 1]; 50 int head[maxn], ecnt = -1; 51 void addEdge(int x, int y) 52 { 53 e[++ecnt] = (Edge){head[x], y}; 54 head[x] = ecnt; 55 } 56 57 ll dp[maxn][maxn]; 58 void dfs(int now, int f) 59 { 60 for(int i = c[now]; i <= p; ++i) dp[now][i] = k[now]; //赋初值 61 for(int i = head[now]; i != -1; i = e[i].nxt) 62 { 63 if(e[i].to == f) continue; 64 dfs(e[i].to, now); 65 for(int j = p; j >= c[now]; --j) 66 for(int h = j; h >= c[now]; --h) 67 dp[now][j] = max(dp[now][j], dp[now][h] + dp[e[i].to][j - h]); 68 } 69 } 70 71 int main() 72 { 73 MYFILE(); 74 Mem(head, -1); 75 n = read(); p = read(); 76 for(int i = 1; i <= n; ++i) c[i] = read(), k[i] = read(); 77 for(int i = 1; i < n; ++i) 78 { 79 int x = read(), y = read(); 80 addEdge(x, y); addEdge(y, x); 81 } 82 dfs(1, 0); 83 write(dp[1][p]), enter; 84 return 0; 85 }
还自己yy了一个O(nv)的算法,虽然过了,然而忘了怎么写的……
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cctype> 8 #include<vector> 9 #include<stack> 10 #include<queue> 11 using namespace std; 12 #define enter puts("") 13 #define space putchar(' ') 14 #define Mem(a, x) memset(a, x, sizeof(a)) 15 #define rg register 16 typedef long long ll; 17 typedef double db; 18 const int INF = 0x3f3f3f3f; 19 const db eps = 1e-8; 20 const int maxn = 105; 21 inline ll read() 22 { 23 ll ans = 0; 24 char ch = getchar(), last = ' '; 25 while(!isdigit(ch)) last = ch, ch = getchar(); 26 while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar(); 27 if(last == '-') ans = -ans; 28 return ans; 29 } 30 inline void write(ll x) 31 { 32 if(x < 0) x = -x, putchar('-'); 33 if(x >= 10) write(x / 10); 34 putchar(x % 10 + '0'); 35 } 36 void MYFILE() 37 { 38 #ifndef mrclr 39 freopen("key.in", "r", stdin); 40 freopen("key.out", "w", stdout); 41 #endif 42 } 43 44 int n, p; 45 int c[maxn], k[maxn]; 46 struct Edge 47 { 48 int nxt, to; 49 }e[maxn << 1]; 50 int head[maxn], ecnt = -1; 51 void addEdge(int x, int y) 52 { 53 e[++ecnt] = (Edge){head[x], y}; 54 head[x] = ecnt; 55 } 56 57 ll dp[maxn][maxn]; 58 void dfs(int now, int f, int x) 59 { 60 if(x < 0) return; 61 for(int i = head[now]; i != -1; i = e[i].nxt) 62 { 63 if(e[i].to == f) continue; 64 for(int j = 0; j <= x; ++j) dp[e[i].to][j] = dp[now][j]; 65 dfs(e[i].to, now, x - c[e[i].to]); 66 for(int j = c[e[i].to]; j <= p; ++j) 67 dp[now][j] = max(dp[now][j], dp[e[i].to][j - c[e[i].to]] + k[e[i].to]); 68 } 69 } 70 71 int main() 72 { 73 MYFILE(); 74 Mem(head, -1); 75 n = read(); p = read(); 76 for(int i = 1; i <= n; ++i) c[i] = read(), k[i] = read(); 77 for(int i = 1; i < n; ++i) 78 { 79 int x = read(), y = read(); 80 addEdge(x, y); addEdge(y, x); 81 } 82 addEdge(0, 1); 83 dfs(0, -1, p); 84 write(dp[0][p]), enter; 85 return 0; 86 }