zoukankan      html  css  js  c++  java
  • POJ 1155

    很久以前做的树形DP题,今天再遇到时,竟然不会了,所以写写。。

    设数组:

    prf[MAX][MAX],cost[MAX],sum[MAX]。分别表示,在第i个结点为根的子树内的情况下,若有j个用户申请看电视,所能得到的最大费用。cost表示传送到i点时所花的费用,而sum表示当前结点为根的子树内已访问的叶子结点的个数(即用户)。

     1 void dfs(int v,int fa){
     2     if(T[v].size()>0){
     3         for(int i=0;i<T[v].size();i++){
     4             dfs(T[v][i],v);
     5         }
     6     }
     7     if(T[v].size()==0)
     8         sum[v]=1;
     9     sum[fa]+=sum[v];
    10         prf[fa][0]=0;
    11         for(int i=sum[fa];i>0;i--){
    12             for(int j=sum[v];j>0;j--){
    13                 if(prf[fa][i-j]!=-INF&&prf[v][j]!=-INF)
    14                 prf[fa][i]=max(prf[fa][i],prf[fa][i-j]+prf[v][j]-cost[v]);
    15         }
    16         }
    17 }
    View Code

    使用深搜,再运用背包来解决。

    for(int i=sum[fa];i>0;i--){

      for(int j=sum[v];j>0;j--){

        if(prf[fa][i-j]!=-INF&&prf[v][j]!=-INF)

          prf[fa][i]=max(prf[fa][i],prf[fa][i-j]+prf[v][j]-cost[v])

      }

    }

    枚举父结点当前已访问的用户数,再枚举当前结点子树内该问了的用户数,若要在父结点的状态中加入j个当前结点有用户,则

    prf[fa][i]=max(prf[fa][i],prf[fa][i-j]+prf[v][j]-cost[v])。这是拿加入j个用户后与当前i个用户的费用的比较。

    前提条件时if(prf[fa][i-j]!=-INF&&prf[v][j]!=-INF),因为要在状态存在的情况下才能进行。

     1 #include <iostream>
     2 #include <vector>
     3 
     4 const int maxn=3010;
     5 const int INF=100000;
     6 using namespace std;
     7 int n,m;
     8 int prf[maxn][maxn];
     9 int cost[maxn];
    10 int sum[maxn];
    11 
    12 vector<int>T[maxn];
    13 
    14 void init(){
    15     for(int i=0;i<=n;i++)
    16         for(int j=0;j<=m;j++)
    17             prf[i][j]=-INF;
    18     memset(cost,0,sizeof(cost));
    19     memset(sum,0,sizeof(sum));
    20     for(int i=0;i<=n;i++)
    21         T[i].clear();
    22 }
    23 int max(int a,int b){
    24     if(a<b)
    25         return b;
    26     return a;
    27 }
    28 void dfs(int v,int fa){
    29     if(T[v].size()>0){
    30         for(int i=0;i<T[v].size();i++){
    31             dfs(T[v][i],v);
    32         }
    33     }
    34     if(T[v].size()==0)
    35         sum[v]=1;
    36     sum[fa]+=sum[v];
    37         prf[fa][0]=0;
    38         for(int i=sum[fa];i>0;i--){
    39             for(int j=sum[v];j>0;j--){
    40                 if(prf[fa][i-j]!=-INF&&prf[v][j]!=-INF)
    41                 prf[fa][i]=max(prf[fa][i],prf[fa][i-j]+prf[v][j]-cost[v]);
    42         }
    43         }
    44 }
    45 
    46 int main(){
    47     while(~scanf("%d%d", &n, &m))
    48     {
    49     init();
    50     int t=0,c,k,y;
    51     T[0].push_back(1);
    52     while((++t)<=n-m){
    53         scanf("%d",&k);
    54         for(int i=1;i<=k;i++){
    55             scanf("%d%d",&y,&c);
    56             T[t].push_back(y);
    57             cost[y]=c;
    58         }
    59     }
    60     for(k=n-m+1;k<=n;k++){
    61         scanf("%d",&c);
    62         prf[k][1]=c;
    63         prf[k][0]=0;
    64     }
    65     dfs(1,0);
    66     for(int i=m;i>=0;i--)
    67         if(prf[1][i]>=0){
    68             printf("%d
    ",i);
    69             break;
    70         }
    71     }
    72     return 0;
    73 }
    View Code
  • 相关阅读:
    VS2008中 没有QT的代码智能提示
    QT的一个奇怪问题,设置了Qt::Tool后,点击弹出对话框的确定取消按钮,程序直接退出。
    QT线程初次使用。遇到的问题。
    QMenu,QT的菜单添加
    VS2008 不能创建C++的项目,解决方法
    VS2008工具,两种加入库的方法。 设置程序运行时目录
    得到弹出菜单QMenu的高度
    QT 修改QTableWidget表头
    QT两个字符串转化函数,避免文字乱码。
    改变QlistWidget的行高
  • 原文地址:https://www.cnblogs.com/jie-dcai/p/3798327.html
Copyright © 2011-2022 走看看