NOIP模拟(20171026)T3 大逃杀

来源:互联网 发布:星星知我心演员胡家玮 编辑:程序博客网 时间:2024/06/07 10:27

一棵带权树,第一次经过一个节点需ti时间,获得wi的武力值
求T时间内获得的最大武力值
n,T300
树形dp神题(告诉了我什么叫转移顺序)
dp[i][j][0/1/2]表示路径的 【起点终点都在i/起点(或终点)在i,另一点在i的子树内(因为路径是可逆的)/起点终点都在i的子树】 内能得到的最大武力值
转移即可(说的容易!!!)
dp[i][j][2]dp[i][jdis(i,v)2k][2]+dp[v][k][0](vson[i])
dp[i][j][2]dp[i][jdis(i,v)2k][0]+dp[v][k][2](vson[i])
dp[i][j][2]dp[i][jdis(i,v)k][1]+dp[v][k][1](vson[i])
dp[i][j][1]dp[i][jdis(i,v)2k][1]+dp[v][k][0](vson[i])
dp[i][j][1]dp[i][jdis(i,v)k][0]+dp[v][k][1](vson[i])
dp[i][j][0]dp[i][jdis(i,v)2k][0]+dp[v][k][0](vson[i])
注意,转移时一定一定一定要用上一个子树的状态来更新这个子树的状态(类似背包的降维优化)
注意,树边权可为0(个中含义自行体会)

#include<bits/stdc++.h>#define LEN 350/*中间一对地方不能反,反了的话,呵呵*/using namespace std;inline int getint(){    int x=0,p=1;    char c=getchar();    while(!isdigit(c)){        if(c=='-')p=-1;        c=getchar();    }    while(isdigit(c)){        x=(x<<3)+(x<<1)+(c^'0');        c=getchar();    }    return x*p;}inline void putint(long long x){    if(x<0){        x=-x;        putchar('-');    }    static int buf[30];    int tot=0;    do{        buf[tot++]=x%10;        x/=10;    }while(x);    while(tot)putchar(buf[--tot]+'0');}int n,T;struct road{    int e,nxt,len;}r[LEN*2];struct node{    int first,fa,w,t;    int dp[LEN][5];}t[LEN];int tot=1;inline void creat(int a,int b,int c){    r[++tot].e=b;    r[tot].len=c;    r[tot].nxt=t[a].first;    t[a].first=tot;}int ans=0;void dfs(int cur){    for(int i=0;i<=300;++i){        for(int j=0;j<5;++j){            t[cur].dp[i][j]=-0xfffffff;        }    }    for(int i=t[cur].t;i<=300;++i){        t[cur].dp[i][0]=t[cur].dp[i][1]=t[cur].dp[i][2]=t[cur].w;    }    for(int i=t[cur].first;i;i=r[i].nxt){        int v=r[i].e;        if(v==t[cur].fa)continue;        t[v].fa=cur;        dfs(v);        for(int j=T;j>=0;--j){                     //不能反            for(int k=0;k<=T;++k){                 //不能反*2                if(j-r[i].len*2-k>=t[cur].t) t[cur].dp[j][2]=                max(t[cur].dp[j][2], t[cur].dp[j-r[i].len*2-k][2]+t[v].dp[k][0]);                if(j-r[i].len*2-k>=t[cur].t) t[cur].dp[j][2]=                max(t[cur].dp[j][2],t[cur].dp[j-r[i].len*2-k][0]+t[v].dp[k][2]);                if(j-r[i].len-k>=t[cur].t) t[cur].dp[j][2]=                max(t[cur].dp[j][2],t[cur].dp[j-r[i].len-k][1]+t[v].dp[k][1]);                if(j-r[i].len*2-k>=t[cur].t) t[cur].dp[j][1]=                max(t[cur].dp[j][1],t[cur].dp[j-r[i].len*2-k][1]+t[v].dp[k][0]);                if(j-r[i].len-k>=t[cur].t) t[cur].dp[j][1]=                max(t[cur].dp[j][1],t[cur].dp[j-r[i].len-k][0]+t[v].dp[k][1]);                if(j-r[i].len*2-k>=t[cur].t) t[cur].dp[j][0]=                max(t[cur].dp[j][0],t[cur].dp[j-r[i].len*2-k][0]+t[v].dp[k][0]);                //不能反*3            }        }    }    //cout<<cur<<endl;    for(int j=T;j>=0;--j){        //cout<<j<<" "<<t[cur].dp[j][0]<<" "<<t[cur].dp[j][1]<<" "<<t[cur].dp[j][2]<<endl;        ans=max(ans,max(t[cur].dp[j][0],(t[cur].dp[j][1],t[cur].dp[j][2])));    }}int main(){    n=getint(),T=getint();    bool f=1;    for(int i=1;i<=n;++i){        t[i].w=getint();        if(t[i].w)f=0;    }    if(f){        cout<<0;        return 0;    }    for(int i=1;i<=n;++i){        t[i].t=getint();    }    for(int i=1;i<n;++i){        int a=getint(),b=getint(),c=getint();        creat(a,b,c),creat(b,a,c);    }    dfs(1);    cout<<ans<<endl;    return 0;}
原创粉丝点击