[树形dp] Jzoj P5819 大逃杀

Description

自从 Y 君退役之后,她就迷上了吃鸡,于是她决定出一道吃鸡的题。
Y 君将地图上的所有地点标号为 1 到 n,地图中有 n − 1 条双向道路连接这些点,通过一条 双向道路需要一定时间,保证从任意一个点可以通过道路到达地图上的所有点。
有些点上可能有资源,Y 君到达一个有资源的点后,可以选择获取资源来使自己的武力值增 加 wi,也可以选择不获取资源。如果 Y 君获取了一个点上的资源,这个点上的资源就会消失,获 取资源不需要时间。
有些点上可能有敌人,Y 君到达一个有敌人的点后,必须花费 ti 秒伏地与敌人周旋,并最终 将敌人消灭。如果 Y 君消灭了一个点上的敌人,这个点上的敌人就会消失。Y 君不能无视敌人继 续前进,因为这样会被敌人攻击。
如果一个点上既有资源又有敌人,Y 君必须先消灭敌人之后才能获取资源,否则就会被敌人 突袭。
游戏开始时,Y 君可以空降到任意一个点上,接下来,她有 T 秒进行行动,T 秒后她就必须 前往中心区域送快递。Y 君希望她前往中心区域送快递时,武力值尽可能大,请你帮助 Y 君设计 路线,以满足她的要求。你只需输出 T 秒后 Y 君的武力值。 
 

Input

第一行由单个空格隔开的两个正整数 n, T,代表点数和时间。
第二行 n 个由单个空格隔开的非负整数代表 wi,如果 wi = 0 代表该点没有武器,
第三行 n 个由单个空格隔开的非负整数代表 ti,如果 ti = 0 代表该点没有敌人。
接下来 n − 1 行每行由单个空格隔开的 3 个非负整数 a, b, c 代表连接 a 和 b 的双向道路,通 过这条道路需要 c 秒。 

Output

输出一行一个整数代表 T 秒后 Y 君的武力值。
 

Sample Input

17 54
5 5 1 1 1 25 1 10 15 3 6 6 66 4 4 4 4
0 1 3 0 0 0 1 3 2 0 6 7 54 0 0 0 0
1 8 3
2 8 3
8 7 7
7 13 0
7 14 0
15 14 2 
16 14 3
17 14 5
7 9 4
9 10 25
10 11 0
10 12 0
7 6 20
3 6 3
3 4 3
3 5 3 

Sample Output

68
 

Data Constraint

题解

  • 这题主要的一个地方就在,没有确定根
  • 那么考虑f[i][j][0/1/2]表示以i为根 用了j时间 引出了0/1/2条链的最大武力值
  • 考虑有几种情况:
  • ①从u绕一圈回来,然后走到u的一个儿子绕一圈回来,f[u][j][0]=max(f[u][j-k-2*v][0]+f[v][k][0])
  • ②走到u的一个儿子绕回来,然后从u走出去不绕回来,f[u][j][1]=max(f[u][j-k-2*v][1]+f[v][k][0])
  • ③从u绕一圈回来,然后走到u的一个儿子不绕回来,f[u][j][1]=max(f[u][j-k-v][0]+f[v][k][1])
  • ④从u绕一圈回来,然后走到u引出两条链,f[u][j][2]=max(f[u][j-k-2*v][0]+f[v][k][2])
  • ⑤走到u的一个儿子绕回来,然后从u引出两条链,f[u][j][2]=max(f[u][j-k-2*v][2]+f[v][k][0])
  • ⑥从u引出两条链,一条走到u的一个儿子,f[u][j][2]=max(f[u][j-k-v][1]+f[v][k][1])
  • 每次要将f[u]赋值到一个数组,不能边跑边变

代码

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <algorithm>
 4 #include <cstring>
 5 using namespace std;
 6 struct edge {int to,from,v;}e[300*2];
 7 int w[310],t[310],n,tim,cnt,head[310];
 8 long long ans,f[310][310][3],a[310][3];
 9 void insert(int x,int y,int v) { e[++cnt].to=y; e[cnt].from=head[x]; e[cnt].v=v; head[x]=cnt; }
10 void dp(int x,int fa)
11 {
12     for (int i=0;i<=tim;i++) f[x][i][0]=f[x][i][1]=f[x][i][2]=(i>=t[x]?w[x]:-0x3f3f3f3f);
13     for (int i=head[x];i;i=e[i].from)
14         if (e[i].to!=fa)
15         {
16             dp(e[i].to,x);
17             memcpy(a,f[x],sizeof(a));
18             for (int j=0;j<=tim;j++)
19                 for (int k=0;k<=tim;k++)
20                 {
21                     if (j+k+2*e[i].v<=tim)
22                     {
23                         f[x][j+k+2*e[i].v][0]=max(f[x][j+k+2*e[i].v][0],a[j][0]+f[e[i].to][k][0]);
24                         f[x][j+k+2*e[i].v][1]=max(f[x][j+k+2*e[i].v][1],a[j][1]+f[e[i].to][k][0]);
25                         f[x][j+k+2*e[i].v][2]=max(f[x][j+k+2*e[i].v][2],a[j][2]+f[e[i].to][k][0]);
26                         f[x][j+k+2*e[i].v][2]=max(f[x][j+k+2*e[i].v][2],a[j][0]+f[e[i].to][k][2]);
27                     }
28                     if (j+k+e[i].v<=tim)
29                     {
30                         f[x][j+k+e[i].v][1]=max(f[x][j+k+e[i].v][1],a[j][0]+f[e[i].to][k][1]);
31                         f[x][j+k+e[i].v][2]=max(f[x][j+k+e[i].v][2],a[j][1]+f[e[i].to][k][1]);
32                     }
33                 }
34         }
35     ans=max(ans,max(f[x][tim][0],max(f[x][tim][1],f[x][tim][2])));
36 }
37 int main()
38 {
39     freopen("toyuq.in","r",stdin);
40     freopen("toyuq.out","w",stdout);
41     scanf("%d%d",&n,&tim);
42     for (int i=1;i<=n;i++) scanf("%d",&w[i]);
43     for (int i=1;i<=n;i++) scanf("%d",&t[i]);
44     for (int i=1;i<=n-1;i++)
45     {
46         int a,b,c;
47         scanf("%d%d%d",&a,&b,&c);
48         insert(a,b,c),insert(b,a,c);
49     }
50     dp(1,0); printf("%lld",ans);
51     return 0;
52 }

猜你喜欢

转载自www.cnblogs.com/Comfortable/p/9483799.html