1774:大逃杀

    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;
} 
View Code

 

posted @ 2020-01-31 23:12  精海臭脚  阅读(366)  评论(1编辑  收藏  举报