HihoCoder 1063 : 缩地 树形DP第二题(对象 边)

时间限制:12000ms

单点时限:1000ms

内存限制:256MB

描述

编织者是 Dota 系列中的一个伪核,拥有很强的生存能力和线上消耗能力。编织者的代表性技能是缩地。缩地带来的隐身、极限移动速度和伤害让它拥有很高的机动性以及赖线和收割的能力。

假设当前作战区域是一棵有根树,编织者所在的位置为根节点1,树中每个节点,有一个权值vi,代表这个节点的收益。树中的每条边,有一个权值wi,代表每条边的长度。编织者从根结点出发,最远累计移动距离时,所能得到的收益的最大值是多少?注意重复经过一个节点收益只能计算一次。

输入

第一行包含一个整数 n (1?≤?n?≤?100),表示节点总数。

接下来的一行,包含 n 个数字,表示一个结点的价值 vi(0?≤?vi?≤?2)。

接下来的 n-1 行,每行三个整数 (aibiwi)。表示一条连接 aibi 节点的边,边长为 wi (1?≤?ai,?bi?≤?n,?1?≤?wi?≤?104)。

接下来的一行包含一个数 q,表示询问总数 (0?≤?q? ≤?100000)。 接下来 q 行,每行包含一个整数 d (?≤?d? ≤?106),表示从根结点出发,最远累计移动的距离 d 。

输出

对于每组询问,输出一行表示对应的询问所能得到的最大收益。

样例输入
3
0 1 1
1 2 5
1 3 3
3
3
10
11
样例输出
1
1
2

简直了,开始把为了方便找错,把200写成20,结果提交后一直wa,200和20又长得怎么像。艾玛啊,咯咯鸡。

注意边界即可,思路及其好想,不多解释。

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<memory>
using namespace std;
const int maxn=220;
const int inf=1e9;

int vis[maxn],n,m;
int dp[maxn][maxn][2],V[maxn];
int Laxt[maxn],Next[maxn],To[maxn],dis[maxn],cnt;

void _add(int u,int v,int d)
{
    Next[++cnt]=Laxt[u];
    Laxt[u]=cnt;
    To[cnt]=v;
    dis[cnt]=d;
}

int _dfs(int u)
{
    vis[u]=true;
    for(int i=Laxt[u];i;i=Next[i]){
        int v=To[i];
        if(vis[v]) continue;
        _dfs(v);
        for(int j=200;j>=0;j--)
        for(int k=j;k>=0;k--){   //此处的边界特殊在可以为j,也可以为0
                dp[u][j][1]=min(dp[u][j][1],dp[u][j-k][1]+dp[v][k][1]+2*dis[i]);
                dp[u][j][0]=min(dp[u][j][0],dp[u][j-k][1]+dp[v][k][0]+dis[i]);
                dp[u][j][0]=min(dp[u][j][0],dp[u][j-k][0]+dp[v][k][1]+2*dis[i]);
        }
    }
}

int main()
{
    int i,j,u,v,d,q;
        scanf("%d",&n);
        for(i=0;i<=100;i++)
         for(j=0;j<=200;j++)
            dp[i][j][0]=dp[i][j][1]=inf;
        for(i=1;i<=n;i++) {
            scanf("%d",&V[i]);
            dp[i][V[i]][1]=0;
            dp[i][V[i]][0]=0;
        }
        for(i=1;i<n;i++){
             scanf("%d%d%d",&u,&v,&d);
             _add(u,v,d);
             _add(v,u,d);
        }
        _dfs(1);
        scanf("%d",&q);
        while(q--){
             scanf("%d",&u);
             for(i=200;i>=1;i--)  if(dp[1][i][0]<=u) break;
             printf("%d\n",i);
        }
    return 0;
}
时间: 2024-11-10 16:15:35

HihoCoder 1063 : 缩地 树形DP第二题(对象 边)的相关文章

树形DP经典题

题目传送门 题意: 给出一棵树,求离每个节点最远的点的距离 思路: 把无根树转化成有根树分析, 对于上面那棵树,要求距结点2的最长距离,那么,就需要知道以2为顶点的子树(蓝色圈起的部分,我们叫它Tree(2)),距顶点2的最远距离L1 还有知道2的父节点1为根节点的树Tree(1)-Tree(2)部分(即红色圈起部分),距离结点1的最长距离+dist(1,2) = L2,那么最终距离结点2最远的距离就是max{L1,L2} f[i][0],表示顶点为i的子树的,距顶点i的最长距离 f[i][1]

POJ 1155 TELE 背包型树形DP 经典题

由电视台,中转站,和用户的电视组成的体系刚好是一棵树 n个节点,编号分别为1~n,1是电视台中心,2~n-m是中转站,n-m+1~n是用户,1为root 现在节点1准备转播一场比赛,已知从一个节点传送数据到达另一个节点,电视台需要一定的费用 若可以传送数据到达用户的节点n-m+1~n,这些用户各自愿意支付一定的费用给电视台 现在电视台希望在不亏本的情况下为尽量多的用户转播比赛 输出最多可以为多少用户转播比赛 背包类型的树形DP第一题 dp[i][j]表示以节点i为根的子树有j个用户获得转播,电视

URAL 1039 Anniversary Party 树形DP 水题

1039. Anniversary Party Time limit: 0.5 secondMemory limit: 8 MB Background The president of the Ural State University is going to make an 80'th Anniversary party. The university has a hierarchical structure of employees; that is, the supervisor rela

POJ 3342 树形DP入门题

题目意思和POJ2342一样,只是多加了一个条件,如果最大方案数唯一,输出Yes,不唯一输出No dp的是时候多加一个变量记录答案是否唯一即可 #include "stdio.h" #include "string.h" #include "vector" using namespace std; struct node { int fa; vector<int>child; }data[210]; struct comp { int

POJ 1947 树形DP入门题

给出N个点,N-1个关系,建出树形图,问最少减去几个边能得到节点数为P的树.典型树形DP题 dp[cur][j] :记录cur结点,要得到一棵j个节点的子树去掉的最少边数 转移方程用的背包的思想 对当前树的每一个子树进行计算 砍掉此子树:   dp[cur][j]=dp[cur][j]+1; 不砍掉:           for (l=0;l<=j;l++)  dp[cur][j]=Min(dp[cur][j],dp[cur][l]+dp[next][j-l]); 枚举从该树中留l个节点其他由新

POJ 2342 树形DP入门题

有一个大学的庆典晚会,想邀请一些在大学任职的人来参加,每个人有自己的搞笑值,但是现在遇到一个问题就是如果两个人之间有直接的上下级关系,那么他们中只能有一个来参加,求请来一部分人之后,搞笑值的最大是多少. 树形DP入门题. DP部分: dp[i][0]表示职员i不来参加party,以i为根的子树的最大搞笑值, dp[i][1]表示职员i来参加party,以i为根的子树的最大搞笑值. 转移方程: dp[cur][1]+=dp[next][0]; dp[cur][0]+=Max(dp[next][1]

URAL 1018 Binary Apple Tree 树形DP 好题 经典

1018. Binary Apple Tree Time limit: 1.0 secondMemory limit: 64 MB Let's imagine how apple tree looks in binary computer world. You're right, it looks just like a binary tree, i.e. any biparous branch splits up to exactly two new branches. We will enu

P2016 战略游戏——树形DP大水题

P2016 战略游戏 树形DP 入门题吧(现在怎么是蓝色标签搞不懂): 注意是看见每一条边而不是每一个点(因为这里错了好几次): #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=3010; int pre[maxn],last[maxn],other[maxn],l; void add(int x,int y) { l++; pre[l]

HDU 2196 Computer 树形DP 经典题

给出一棵树,边有权值,求出离每一个节点最远的点的距离 树形DP,经典题 本来这道题是无根树,可以随意选择root, 但是根据输入数据的方式,选择root=1明显可以方便很多. 我们先把边权转化为点权,放在数组cost中 令tree(i)表示以节点i为根的子树 对于节点i,离该节点最远的点要不就是在tree(i)中,要不就是在father(i)上面 令: dp[i][1] : 在子树tree(i)中,离i最远的距离 dp[i][2] : 在子树tree(i)中,离i第二远的距离 (递推的时候需要)