BZOJ 1017 魔兽地图DotR(树形DP)
题意:有两类装备,高级装备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 }