【HDOJ】1011 Starship Troopers

本文将深入浅出地讲解树形动态规划的基本概念,并通过一个典型的例子来展示如何应用这种算法解决实际问题。通过具体的代码实现,读者可以直观地理解动态规划的思想,并学会在树状结构中进行状态转移。

第一道树形DP。很容易理解。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 
 5 #define MAXN 105
 6 
 7 typedef struct {
 8     int n, p;
 9 } room_t;
10 
11 room_t rooms[MAXN];
12 int adj[MAXN][MAXN];
13 int dp[MAXN][MAXN];
14 bool visit[MAXN];
15 int n, m;
16 
17 int max(int a, int b) {
18     return a>b ? a:b;
19 }
20 
21 void dfs(int r) {
22     int i, j, k, num, v;
23     
24     visit[r] = true;
25     num = (rooms[r].n+19) / 20;
26     for (i=num; i<=m; ++i)
27         dp[r][i] = rooms[r].p;
28         
29     for (i=1; i<=adj[r][0]; ++i) {
30         v = adj[r][i];
31         if (visit[v])
32             continue;
33         dfs(v);
34         for (j=m; j>=num; --j) {
35             for (k=1; k+j<=m; ++k) {
36                 if (dp[v][k]) {
37                     dp[r][j+k] = max(dp[r][j+k], dp[r][j]+dp[v][k]);
38                 }
39             }
40         }
41     }
42 }
43 
44 int main() {
45     int i, j, k;
46     
47 #ifndef ONLINE_JUDGE
48     freopen("data.in", "r", stdin);
49 #endif
50 
51     while (scanf("%d %d", &n, &m) != EOF) {
52         if (n==-1 && m==-1)
53             break;
54         memset(adj, 0, sizeof(adj));
55         memset(visit, false, sizeof(visit));
56         memset(dp, 0, sizeof(dp));
57         for (i=1; i<=n; ++i) {
58             scanf("%d %d", &rooms[i].n, &rooms[i].p);
59         }
60         for (i=1; i<n; ++i) {
61             scanf("%d %d", &j, &k);
62             ++adj[j][0];
63             ++adj[k][0];
64             adj[j][adj[j][0]] = k;
65             adj[k][adj[k][0]] = j;
66         }
67         if (m == 0) {
68             printf("0\n");
69             continue;
70         }
71         dfs(1);
72         printf("%d\n", dp[1][m]);
73     }
74 
75     return 0;
76 }

 

转载于:https://www.cnblogs.com/bombe1013/p/4169292.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值