有线电视网【P1273】【树形DP】

题目链接

    一道树形DP,但是它的想法还是可以称之为树形背包,依旧是从大数往下推,我的这一道题中有对树形背包的完整讲解,这里呢,就是DP的列写得怎么样列写?dp[i][j],以i号节点为根节点时,取j个人的时候,需要的代价,我们希望最后的代价为“>=0”的。

 

完整代码:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
using namespace std;
typedef long long ll;
const int maxN=3005;
int N, M;
int dp[maxN][maxN], val[maxN];
struct eddge
{
    int nex, val;
    eddge(int a=0, int b=0):nex(a), val(b) {}
};
vector<eddge> vt[maxN];
int dfs(int u)
{
    dp[u][0]=0;
    if(u>N-M) { dp[u][1]=val[u]; return 1; }
    int son=0, tmp=0, len=(int)vt[u].size();
    for(int i=0; i<len; i++)
    {
        int v=vt[u][i].nex, cost=vt[u][i].val;
        son+=(tmp=dfs(v));
        for(int j=son; j>=1; j--)
        {
            for(int k=1; k<=tmp; k++)
            {
                if(j>=k) dp[u][j]=max(dp[u][j], dp[u][j-k]+dp[v][k]-cost);
            }
        }
    }
    return son;
}
int main()
{
    scanf("%d%d", &N, &M);
        for(int i=1; i<=(N-M); i++)
        {
            int e1, e2, e3;
            scanf("%d", &e1);
            while(e1--)
            {
                scanf("%d%d", &e2, &e3);
                vt[i].push_back(eddge(e2, e3));
            }
        }
        for(int i=(N-M+1); i<=N; i++) scanf("%d", &val[i]);
    for(int i=1; i<=N; i++) for(int j=1; j<=N; j++) dp[i][j]=-1000000;
        dfs(1);
        for(int i=M; i>=0; i--)
        {
            if(dp[1][i]>=0)
            {
                printf("%d\n", i);
                break;
            }
            else if(i==0)
            {
                printf("0\n");
                break;
            }
        }
    return 0;
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wuliwuliii

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值