zoukankan      html  css  js  c++  java
  • 洛谷 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
    ",ans);
        return 0;
    } 
  • 相关阅读:
    用户使用调查报告
    Beta总结
    Beta冲刺Day7
    Beta冲刺Day6
    Beta冲刺Day5
    Beta冲刺Day4
    Beta冲刺Day3
    Beta冲刺Day2
    Beta冲刺Day1
    Beta预备
  • 原文地址:https://www.cnblogs.com/yanlifneg/p/5831446.html
Copyright © 2011-2022 走看看