1774:大逃杀
时间限制: 1000 ms 内存限制: 262144 KB
提交数: 49 通过数: 19
【题目描述】
将地图上的所有地点标号为1到n,地图中有n-1
条双向道路连接这些点,通过一条双向道路需要一定时间,保证从任意一个点可以通过道路到达地图上的所有点。
有些点上可能有资源,到达一个有资源的点后,可以获取资源来增加 wi的武力值。
资源被获取后就会消失,获取资源不需要时间。可选择不获取资源。
有些点上可能有敌人,到达一个有敌人的点后,必须花费ti秒与敌人周旋,并将敌人消灭。敌人被消灭后就会消失。不能无视敌人。
如果一个点上既有资源又有敌人,必须先消灭敌人才能获取资源。
游戏开始时Y君可以空降到任意一个点上,接下来,有T秒时间行动,Y君希望游戏结束时,武力值尽可能大。
【输入】
第一行由单个空格隔开的两个正整数 n,T,代表点数和时间。
第二行n个由单个空格隔开的非负整数代表 wi,如果wi=0表示该点没有资源。
第三行n个由单个空格隔开的非负整数代表 ti,如果ti=0代表该点没有敌人。
接下来n-1行每行由单个空格隔开的3个非负整数a,b,c表示连接a和b的双向道路,通过这条道路需要c秒。
【输出】
输出一行一个整数代表T秒后Y君的武力值。
【输入样例】
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
【输出样例】
68
【提示】
【数据规模】
对于100%的数据,n,T≤300,0≤wi,ti,c≤106,1≤a,b≤n。
【题解】
因为起点不确定,所以定义三种状态f,g,h[i][j]分别表示在i子树内用了j的时间,f:从i出发,去了子树内在回到i最大收益,g:从i出发,到达子树内任意节点,h从子树内出发,经过i到达子树内任一节点最大收益。根据子树内信息依次转移即可。
代码如下:
#include<bits/stdc++.h> using namespace std; const int N=305; int f[N][N],g[N][N],h[N][N],last[N],size,w[N],t[N],n,T,ans; struct pigu { int dao,ne,quan; }a[N<<1]; inline void lingjiebiao(int x,int y,int z) { a[++size].dao=y; a[size].quan=z; a[size].ne=last[x]; last[x]=size; } //f表示下去了回来,g表示下去了不回来,h表示从下头来 inline void dfs(int now,int fa) { if(t[now]>T) return; for(int i=last[now];i;i=a[i].ne) { if(a[i].dao==fa) continue; dfs(a[i].dao,now); for(int j=T;j>=t[now];j--) { for(int k=j-a[i].quan;k>=t[now];k--) { int h1=f[now][k],h2=g[now][k],h3=h[now][k];//k表示之前用了好多时间了。 int shen=j-k-a[i].quan; if(shen>=t[a[i].dao]) { g[now][j]=max(g[now][j],h1+g[a[i].dao][shen]); h[now][j]=max(h[now][j],h2+g[a[i].dao][shen]); } shen-=a[i].quan; if(shen>=t[a[i].dao]) { g[now][j]=max(g[now][j],h2+f[a[i].dao][shen]); f[now][j]=max(f[now][j],f[a[i].dao][shen]+h1); h[now][j]=max(h[now][j],h3+f[a[i].dao][shen]); h[now][j]=max(h[now][j],h[a[i].dao][shen]+h1); } } ans=max(ans,h[now][j]); } } } int main() { cin>>n>>T; for(int i=1;i<=n;i++) cin>>w[i]; for(int i=1;i<=n;i++) { cin>>t[i]; if(t[i]<=T) f[i][t[i]]=g[i][t[i]]=h[i][t[i]]=w[i]; } for(int i=1,x,y,z;i<=n-1;i++) { cin>>x>>y>>z; lingjiebiao(x,y,z); lingjiebiao(y,x,z); } dfs(1,0); cout<<ans; }
原文地址:https://www.cnblogs.com/betablewaloot/p/12247208.html