zoj 3626 Treasure Hunt I

这题是在一个图中收集点上的价值,树形DP+01背包。题目的意思是在m天内要回到原点,但是按照前m/2天收集,后m/2天原路返回来做结果是对的。用dp[k][i]表示从k点出发,用 i 天能获得的最大值,状态转移方程为 dp[k][a] <?= dp[k][a - w[k][u] - b] + dp[u][b]。意思是总共a天,花了w[k][u]天从k走到u点(k与u相连),用b天从u开始收集,至于剩下的a -w[k][u] -b天可能用不到,就是用来凑数的。

下面的代码很悲剧,时限2000它跑出个2001,因为里面有个错误。更奇葩的是OJ居然不给WA,也不给RE,我很想知道犯了这个错误是怎么还能正常运行同时保证结果正确的。当然了,我是知道这个错误在哪儿的。

 1 #include <stdio.h>
 2 #include <string.h>
 3 const int N = 102;
 4 int fst[N],nxt[N],to[N<<1];
 5 int dp[N][N],T[N][N],V[N];
 6 bool vis[N];
 7 int n,m,k;
 8 void max(int &a,int b)
 9 {
10     if(a < b) a = b;
11 }
12 void dfs(int u)
13 {
14     int i,j,v,e;
15     vis[u] = 1;
16     for(e = fst[u];;e = nxt[e])
17     {
18         if(e == -1) return ;
19         v = to[e];
20         if(!vis[v])
21         {
22             dfs(v);
23         for(i = m; i >= T[u][v]; i--)
24             for(j = 0; j <= i-T[u][v]; j++)
25                 max(dp[u][i],dp[u][i-T[u][v]-j]+dp[v][j]);
26         }
27     }
28 }
29 int main()
30 {
31     int u,v,w,i,j;
32     while(~scanf("%d",&n))
33     {
34         memset(fst,-1,sizeof fst);
35         memset(vis,0,sizeof vis);
36         for(i = 1; i <= n; i++)
37             scanf("%d",&V[i]);
38         for(i = j = 1; i < n; i++)
39         {
40             scanf("%d%d%d",&u,&v,&w);
41             T[u][v] = T[v][u] = w;
42             nxt[j] = fst[u];
43             to[j] = v;
44             fst[u] = j++;
45             nxt[j] = fst[v];
46             to[j] = u;
47             fst[v] = j++;
48         }
49         scanf("%d%d",&k,&m);
50         m /= 2;
51         for(i = 1; i <= n; i++)
52             for(j = 0; j <= m; j++)
53                 dp[i][j] = V[i];
54         dfs(k);
55         printf("%d\n",dp[k][m]);
56     }
57     return 0;
58 }
原文地址:https://www.cnblogs.com/lzxskjo/p/2663300.html