1 条题解
-
0
🧠 题解(Solution) 思路:树状dp。由于求的是最多多少用户,那么我们可以把用户个数当成一个状态。dp[i][j]代表i节点为根节点的子树j个用户的时候最大剩余费用。 则dp[i][j] = max(dp[i][j], dp[i][k]+dp[son][j-k]-w[i][son]);
注意两点,第一点是上面式子中的dp[i][k]必须先用一个tem[MAX]数组提取出来,因为在计算的过程中会相互影响。第二点是价值可能是负值,所以dp初始化的时候要初始化为负的最大值。
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; struct node { int now,val,next; } tree[9005]; int n,m,len = 0; int num[3005],head[3005],dp[3005][3005],tem[3005]; void add(int i,int x,int y) { tree[len].now = x; tree[len].val = y; tree[len].next = head[i]; head[i] = len++; } void dfs(int root) { int i,j,k,p; for(i = head[root]; i!=-1; i=tree[i].next) { p = tree[i].now; dfs(p); for(j = 0; j<=num[root]; j++) tem[j] = dp[root][j]; for(j = 0; j<=num[root]; j++) { for(k = 1; k<=num[p]; k++) dp[root][k+j] = max(dp[root][j+k],tem[j]+dp[p][k]-tree[i].val); } num[root]+=num[p]; } } int main() { int i,j,k,a,b; while(~scanf("%d%d",&n,&m)) { memset(head,-1,sizeof(head)); for(i = 1; i<=n-m; i++) { scanf("%d",&k); num[i] = 0; for(j = 0; j<k; j++) { scanf("%d%d",&a,&b); add(i,a,b); } } for(i = 1; i<=n; i++) { for(j = 1; j<=m; j++) dp[i][j] = -10000000; } for(i = n-m+1; i<=n; i++) { num[i] = 1; scanf("%d",&dp[i][1]); } dfs(1); for(i = m; i>=0; i--) { if(dp[1][i]>=0) { printf("%d\n",i); break; } } } return 0; }
- 1
信息
- ID
- 156
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 3
- 已通过
- 1
- 上传者