洛谷 P1273 有线电视网(dp)

/*
想了半天没想出状态 自己还是太弱了 QAQ
题目问的是最多供给多少户 一般想法是把这个值定义为状态量
没想出来QAQ....看了看题解的状态 很机智....
f[i][j]表示i的子树 选了j个叶子的最大收益
这样 不亏本就是收益>=0
转移的话 先搜一下这个子树有几个叶子 然后枚举儿子
枚举当前儿子分几个叶子 这里的枚举顺序有套路
从大到小枚举i分几个 从小到大枚举j分几个
这样可以避免 重复选择
注意初始化
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 3010
using namespace std;
int n,m,p,head[maxn],num,f[maxn][maxn],ans,c[maxn];
struct node{
    int v,t,pre;
}e[maxn];
void Add(int from,int to,int dis){
    num++;e[num].v=to;
    e[num].t=dis;
    e[num].pre=head[from];
    head[from]=num;
}
int Dfs(int u)
{
    if(u>p){
        f[u][1]=c[u];
        return 1;
    }
    int s=0;
    for(int i=head[u];i;i=e[i].pre){
        int v=e[i].v;
        int x=Dfs(v);s+=x;
        for(int j=s;j>=1;j--)
            for(int k=1;k<=x;k++)
                f[u][j]=max(f[u][j],f[u][j-k]+f[v][k]-e[i].t);
    }
    return s;
}
int main()
{
    scanf("%d%d",&n,&m);p=n-m;
    for(int i=1;i<=p;i++){
        int x,y,z;
        scanf("%d",&x);
        for(int j=1;j<=x;j++){
            scanf("%d%d",&y,&z);
            Add(i,y,z);
        }
    }
    for(int i=p+1;i<=n;i++)
        scanf("%d",&c[i]);
    memset(f,-127/3,sizeof(f));
    for(int i=1;i<=n;i++)
        f[i][0]=0;
    Dfs(1);
    for(int i=0;i<=m;i++)
        if(f[1][i]>=0)ans=max(ans,i);
    printf("%d\n",ans);
    return 0;
} 
时间: 2024-12-13 01:42:31

洛谷 P1273 有线电视网(dp)的相关文章

洛谷 P1273 有线电视网

2016-05-31 13:25:45 题目链接: 洛谷 P1273 有线电视网 题目大意: 在一棵给定的带权树上取尽量多的叶子节点,使得sigma(val[选择的叶子节点])-sigma(cost[经过的边])>=0 解法: 树状DP 背包DP DP[i][j]表示i号节点为根的子树中选择了j个叶子节点所得到的最大利润 转移方程 DP[i][j]=max(DP[i][j],DP[i][j-k]+DP[son][k]-cost[son][i]); 需要注意的地方 写初始值的时候要注意除了DP[i

洛谷1273 有线电视网

本题地址:http://www.luogu.org/problem/show?pid=1273 题目描述 某收费有线电视网计划转播一场重要的足球比赛.他们的转播网和用户终端构成一棵树状结构,这棵树的根结点位于足球比赛的现场,树叶为各个用户终端,其他中转站为该树的内部节点. 从转播站到转播站以及从转播站到所有用户终端的信号传输费用都是已知的,一场转播的总费用等于传输信号的费用总和.     现在每个用户都准备了一笔费用想观看这场精彩的足球比赛,有线电视网有权决定给哪些用户提供信号而不给哪些用户提供

luogu P1273 有线电视网

题目链接 luogu P1273 有线电视网 题解 树形背包 dp[i][j]表示在以i为根的子树中,满足j个客户的需求所能获得的最大收益 代码 #include<cstdio> #include<algorithm> #include<cstring> const int maxn = 3007; //using namespace std; inline int read() { int x = 0,f = 1; char c = getchar(); while(

洛谷P2018 消息传递 树形DP

洛谷P2018 消息传递 树形DP dp[ u ] 表示 u 节点 已经被传到,然后将其字节点都传到所需要的最少时间 可知一个原则 一个树中的子树中如果同时开始传,那么最晚才能传到的,那他肯定最先开始传 因为本身需要的时间就大了,如果再晚一点开始,就要更晚才能结束了 也就是说从叶子向根传,将一个树中的子树 按照 他们直接传所需要的时间排序优先传大的,再传小的 也就是一个点 只要负责好传到他们的儿子那些点就够了 1 #include <cstdio> 2 #include <cmath&g

洛谷 P1273 【有线电视网】

题目描述 某收费有线电视网计划转播一场重要的足球比赛.他们的转播网和用户终端构成一棵树状结构,这棵树的根结点位于足球比赛的现场,树叶为各个用户终端,其他中转站为该树的内部节点. 从转播站到转播站以及从转播站到所有用户终端的信号传输费用都是已知的,一场转播的总费用等于传输信号的费用总和. 现在每个用户都准备了一笔费用想观看这场精彩的足球比赛,有线电视网有权决定给哪些用户提供信号而不给哪些用户提供信号. 写一个程序找出一个方案使得有线电视网在不亏本的情况下使观看转播的用户尽可能多. 输入 输入文件的

Luogu P1273 有线电视网(树形dp+背包)

题面 题目描述 某收费有线电视网计划转播一场重要的足球比赛.他们的转播网和用户终端构成一棵树状结构,这棵树的根结点位于足球比赛的现场,树叶为各个用户终端,其他中转站为该树的内部节点. 从转播站到转播站以及从转播站到所有用户终端的信号传输费用都是已知的,一场转播的总费用等于传输信号的费用总和. 现在每个用户都准备了一笔费用想观看这场精彩的足球比赛,有线电视网有权决定给哪些用户提供信号而不给哪些用户提供信号. 写一个程序找出一个方案使得有线电视网在不亏本的情况下使观看转播的用户尽可能多. 输入输出格

洛谷P1108 低价购买[DP | LIS方案数]

题目描述 “低价购买”这条建议是在奶牛股票市场取得成功的一半规则.要想被认为是伟大的投资者,你必须遵循以下的问题建议:“低价购买:再低价购买”.每次你购买一支股票,你必须用低于你上次购买它的价格购买它.买的次数越多越好!你的目标是在遵循以上建议的前提下,求你最多能购买股票的次数.你将被给出一段时间内一支股票每天的出售价(2^16范围内的正整数),你可以选择在哪些天购买这支股票.每次购买都必须遵循“低价购买:再低价购买”的原则.写一个程序计算最大购买次数. 这里是某支股票的价格清单: 日期 1 2

洛谷P1244 青蛙过河 DP/思路

又是一道奇奇怪怪的DP(其实是思路题). 原文戳>>https://www.luogu.org/problem/show?pid=1244<< 这题的意思给的挺模糊,需要一定的人生经验理解能力. 题目想必已知,我就提几点可能会搞错的点吧. 1.题目说了青蛙可以:A→B(表示可以从A跳到B,下同),A→C,A→D,C→B,D→B,D→C,C→D:但却不能跳到A,B上再跳回来.所以不可以脑补成汉内塔那种跳法. 2.青蛙只能跳到比它大1号的青蛙上面,而不是比他大的青蛙就行.所以不可以脑补

[P1273] 有线电视网 (树形DP+分组背包)

题意:给出一棵树,有边权,只有叶子节点有点权,求一个合法方案(选择走到哪几个叶子节点,且路径上的权值和 <= 要走到的叶子节点的点权和),使得选择的叶子节点数量尽量的多: 解法:树形DP+分组背包: 1.树形DP:这是一棵树,所以叫树形DP: 2.分组背包:在这里主要是运用到了它的思想:我们可以设 f[i][j],表示 i节点选择了 j个叶子节点的费用最大值:假设现在在 x节点,它的下面有 n个叶子节点(不是它的儿子),那么我们就要处理出它选 1,2,3,……,n 个叶子节点的情况,但是由于这是