码迷,mamicode.com
首页 > 其他好文 > 详细

洛谷 P1273 有线电视网(dp)

时间:2016-09-01 22:49:07      阅读:282      评论:0      收藏:0      [点我收藏+]

标签:

/*
想了半天没想出状态 自己还是太弱了 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;
} 

 

洛谷 P1273 有线电视网(dp)

标签:

原文地址:http://www.cnblogs.com/yanlifneg/p/5831446.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!