zoukankan      html  css  js  c++  java
  • 【洛谷P1273】有线电视网

    有线电视网

    题目链接

    树形DP,分组背包

    dp[u][i][j]表示以u为根的子树,前i个子树中选j个用户的最大收益.

    dp[u][size[u]][0]=0;

    dp[u][i][j]=max(dp[u][i][j],dp[u][i-1][j-k]+dp[v][size[v]][k]-w[u][v]);

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    #define N 3010
    int n,m,dp[N][N],val[N];
    struct NODE{
        int to,w,next;
    } e[N];
    int Head[N],num;
    inline void add(int x,int y,int w){
        e[++num].to=y;
        e[num].w=w;
        e[num].next=Head[x];
        Head[x]=num;
    }
    inline int read(){
        int x=0; char c=getchar();
        while(c<'0'||c>'9') c=getchar();
        while('0'<=c&&c<='9') { x=(x<<3)+(x<<1)+c-'0'; c=getchar(); }
        return x;
    }
    int dfs(int u){
        dp[u][0]=0;
        if(u>n-m){
            dp[u][1]=val[u];
            return 1;
        }
        int sum=0;
        for(int i=Head[u];i;i=e[i].next){
            int v=e[i].to;
            int sz=dfs(v);
            for(int j=sum;j>=0;j--)
             for(int k=1;k<=sz;k++)
              dp[u][j+k]=max(dp[u][j+k],dp[u][j]+dp[v][k]-e[i].w);
            sum+=sz;
        }
        return sum+1;
    }
    int main()
    {
        memset(dp,~0x3f,sizeof(dp));
        n=read(); m=read();
        int snum,y,w;
        for(int i=1;i<=n-m;i++){
            snum=read();
            while(snum--){
                y=read(); w=read();
                add(i,y,w);
            }
        }
        for(int i=n-m+1;i<=n;i++)
         val[i]=read();
        dfs(1);
        int ans=0;
        for(ans=m;ans>=1;ans--)
         if(dp[1][ans]>=0) break;
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    典型格雷码-数学规律
    合并两个有序数组
    从fragment跳转到Activity
    fragment如何findviewby
    布局和位置
    preferencefragment
    AndroidStudio导入support-v13
    一些属性作用
    菜单menu
    ActionBar
  • 原文地址:https://www.cnblogs.com/yjkhhh/p/9415794.html
Copyright © 2011-2022 走看看