POJ 1155 TELE

题目意思:
  电视台发送信号给很多用户,每个用户愿意出一些钱,电视台经过的路线都有一定费用,求电视台不损失的情况下最多给多少用户发送信号。
多么明显的有依赖性的01背包:
  dp[i][j]对于借点I 背包容量J ;

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <cstdlib>
using namespace std;
const int maxn=3004;
const int INF=0x7ffffff;
struct Edge
{
    int to,dis,pre;
    Edge(int to=0,int dis=0,int pre=0):to(to),dis(dis),pre(pre){}
};
Edge  edge[maxn];
int head[maxn],pos;
int money[maxn];
int dp[maxn][maxn];
void inint()
{
    memset(head,-1,sizeof(head));
    pos=0;
}
void add_edge(int &s,int &to,int &dis)
{
    edge[pos]=Edge(to,dis,head[s]);
    head[s]=pos++;
}
int n,m;
int dfs(int s)
{

    int ans=0,key;
    dp[s][0]=0;
    for(int i=1;i<maxn;i++)dp[s][i]=-INF;

    for(int i=head[s];i!=-1;i=edge[i].pre)
    {
        Edge &tmp=edge[i];
        if(tmp.to==-1) key=0;
        else key=dfs(tmp.to);
        ans+=key;
        for(int j=ans;j>=1;j--)
            for(int t=1;t<=key;t++)
            {
                if(j<t)break;
                dp[s][j]=max(dp[s][j],dp[s][j-t]+dp[tmp.to][t]-tmp.dis);
            }
    }
    if(s>(n-m))
    {
        ans++;
        for(int j=ans;j>=1;j--)  dp[s][j]=dp[s][j-1]+money[s];
    }
    return ans;
}
int main()
{
    int num,a,b;
    while(~scanf("%d%d",&n,&m))
    {
        inint();
        for(int i=1;i<=(n-m);i++)
        {

            scanf("%d",&num);
            for(int w=1;w<=num;w++)
                scanf("%d%d",&a,&b),
                add_edge(i,a,b);
        }
        for(int i=n-m+1;i<=n;i++)scanf("%d",&money[i]);
        dfs(1);
        for(int i=n;i>=0;i--)
            if(dp[1][i]>=0){printf("%d\n",i);break;}
    }
    return 0;
}

 

posted @ 2014-07-30 09:31  默默无语敲代码  阅读(130)  评论(0编辑  收藏  举报