[树形dp] Jzoj P5819 大逃杀
题解
- 这题主要的一个地方就在,没有确定根
- 那么考虑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 }