JZOJ5819.【NOIP提高A组模拟2018.8.15】大逃杀

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

这里写图片描述

题解

n不是很大。
f i , j 表示在第i个节点,进入i的子树,然后回到i的最大值,
g i , j 表示在第i个节点,进入i的子树,然后不回到i的最大值,
h i , j 表示在第i个节点,进入i的子树,然后经过i的最大值。

转移就非常简单,类似背包。
总的时间复杂度就是 O ( n T 2 )

code

//#pragma GCC optimize(2)
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string.h>
#include <cmath>
#include <math.h>
#include <time.h>
#define ll long long
#define N 303
#define M 603
#define db double
#define P putchar
#define G getchar
#define inf 998244353
#define pi 3.1415926535897932384626433832795
using namespace std;
char ch;
void read(int &n)
{
    n=0;
    ch=G();
    while((ch<'0' || ch>'9') && ch!='-')ch=G();
    ll w=1;
    if(ch=='-')w=-1,ch=G();
    while('0'<=ch && ch<='9')n=(n<<3)+(n<<1)+ch-'0',ch=G();
    n*=w;
}

int n,m,x,y,z,T[N],w[N];
int nxt[M],lst[N],v[M],c[M],to[M],tot;
ll f[N][N],g[N][N],h[N][N],ff[N],gg[N],hh[N],ans;

void mx(ll& x,ll y){x=(x>y?x:y);}

void ins(int x,int y,int z)
{
    nxt[++tot]=lst[x];
    to[tot]=y;
    v[tot]=z;
    lst[x]=tot;
}

void dfs(int x,int fa)
{
    int t,y;
    for(int i=0;i<=m;i++)
        if(i>=T[x])f[x][i]=g[x][i]=h[x][i]=w[x];else f[x][i]=g[x][i]=h[x][i]=-2147483647;
    for(int i=lst[x];i;i=nxt[i])
        if(to[i]!=fa)
        {
            dfs(y=to[i],x);
            memcpy(ff,f[x],sizeof(ff));
            memcpy(gg,g[x],sizeof(gg));
            memcpy(hh,h[x],sizeof(hh));
            for(int j=0;j<=m;j++)
                for(int k=0;k<=m;k++)
                {
                    if((t=j+k+(v[i]<<1))<=m)
                    {
                        mx(f[x][t],ff[j]+f[y][k]);
                        mx(g[x][t],gg[j]+f[y][k]);
                        mx(h[x][t],hh[j]+f[y][k]);
                        mx(h[x][t],ff[j]+h[y][k]);
                    }

                    if((t=j+k+v[i])<=m)
                    {
                        mx(g[x][t],ff[j]+g[y][k]);
                        mx(h[x][t],gg[j]+g[y][k]);
                    }
                }           
        }
    mx(ans,max(h[x][m],g[x][m]));
    mx(ans,f[x][m]);
}

int main()
{
    freopen("toyuq.in","r",stdin);
    freopen("toyuq.out","w",stdout);
    read(n);read(m);
    for(int i=1;i<=n;i++)read(w[i]);
    for(int i=1;i<=n;i++)read(T[i]);
    for(int i=1;i<n;i++)
        read(x),read(y),read(z),ins(x,y,z),ins(y,x,z);
    dfs(1,0);
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/lijf2001/article/details/81807151