首页 > 技术文章 > BZOJ 1017 魔兽地图DotR(树形DP)

qzqzgfy 2016-06-02 18:55 原文

题意:有两类装备,高级装备A和基础装备B。现在有m的钱。每种B有一个单价和可以购买的数量上限。每个Ai可以由Ci种其他物品合成,给出Ci种其他物品每种需要的数量。每个装备有一个贡献值。求最大的贡献值。已知物品的合成路线是一个严格的树模型。即有一种物品不会合成其他任意物品,其余物品都会仅仅可用作合成另外一种物品

思路:f[i][j][k],代表第i个物品,花费了j,向上提供k个i物品。

 1 #include<algorithm>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<iostream>
 6 int f[55][2005][105];
 7 int num[20005],a[20005],b[20005],c[105][105],d[105][105];
 8 int n,m,vis[200005],dp[55][2005],w[20005],pd[20005];
 9 void dfs(int x){
10     if (!num[x]){
11         b[x]=std::min(b[x],m/a[x]);
12         for (int i=0;i<=b[x];i++)
13          for (int j=0;j<=i;j++)
14           f[x][i*a[x]][j]=w[x]*(i-j);
15         return;  
16     }
17     b[x]=0x7fffffff;
18     for (int i=1;i<=num[x];i++){
19         int pur=c[x][i];
20         dfs(pur);
21         b[x]=std::min(b[x],b[pur]/d[x][i]);
22         a[x]+=d[x][i]*a[pur];
23     }
24     b[x]=std::min(b[x],m/a[x]);
25     for (int t=0;t<=b[x];t++){
26         memset(dp,-0x3f3f3f3f,sizeof dp);
27         dp[0][0]=0; 
28         for (int i=1;i<=num[x];i++)
29          for (int j=0;j<=m;j++)
30           for (int k=0;k<=j;k++)
31            dp[i][j]=std::max(dp[i][j],dp[i-1][j-k]+f[c[x][i]][k][t*d[x][i]]);
32         for (int j=0;j<=m;j++)
33          for (int k=0;k<=t;k++)
34           f[x][j][k]=std::max(f[x][j][k],dp[num[x]][j]+(t-k)*w[x]);
35     }
36 }
37 int main(){
38     char s[20];
39     scanf("%d%d",&n,&m);
40     for (int i=1;i<=n;i++){
41         scanf("%d",&w[i]);
42         scanf("%s",s+1);
43         if (s[1]=='A') pd[i]=1;else pd[i]=0;
44         num[i]=0;
45         if (pd[i]==0) {
46           scanf("%d%d",&a[i],&b[i]);
47           num[i]=0;
48           continue;
49         }
50         scanf("%d",&num[i]);
51         for (int j=1;j<=num[i];j++){
52          scanf("%d%d",&c[i][j],&d[i][j]);
53          vis[c[i][j]]=1; 
54         }
55     }
56     int i;
57     for (i=1;i<=n;i++) if (!vis[i]) break;
58     int root=i;
59     memset(f,-0x3f3f3f3f,sizeof f);
60     dfs(root);
61     int ans=0;
62     for (int i=0;i<=m;i++)
63      for (int j=0;j<=b[root];j++)
64       ans=std::max(ans,f[root][i][j]);
65     printf("%d\n",ans);  
66 }

 

推荐阅读