1017: [JSOI2008]魔兽地图DotR

Description

  DotR (Defense of the Robots) Allstars是一个风靡全球的魔兽地图,他的规则简单与同样流行的地图DotA 
(Defense of the Ancients) Allstars。DotR里面的英雄只有一个属性——力量。他们需要购买装备来提升自己的
力量值,每件装备都可以使佩戴它的英雄的力量值提高固定的点数,所以英雄的力量值等于它购买的所有装备的力
量值之和。装备分为基本装备和高级装备两种。基本装备可以直接从商店里面用金币购买,而高级装备需要用基本
装备或者较低级的高级装备来合成,合成不需要附加的金币。装备的合成路线可以用一棵树来表示。比如,Sange 
and Yasha的合成需要Sange,Yasha和Sange and Yasha Recipe Scroll三样物品。其中Sange又要用Ogre Axe, Belt
 of Giant Strength和 Sange Recipe Scroll合成。每件基本装备都有数量限制,这限制了你不能无限制地合成某
些性价比很高的装备。现在,英雄Spectre有M个金币,他想用这些钱购买装备使自己的力量值尽量高。你能帮帮他
吗?他会教你魔法Haunt(幽灵附体)作为回报的。

Input

  第一行包含两个整数,N (1 <= n <= 51) 和 m (0 <= m <= 2,000)。分别表示装备的种类数和金币数。装备
用1到N的整数编号。接下来的N行,按照装备1到装备n的顺序,每行描述一种装备。每一行的第一个正整数表示这
个装备贡献的力量值。接下来的非空字符表示这种装备是基本装备还是高级装备,A表示高级装备,B表示基本装备
。如果是基本装备,紧接着的两个正整数分别表示它的单价(单位为金币)和数量限制(不超过100)。如果是高
级装备,后面紧跟着一个正整数C,表示这个高级装备需要C种低级装备。后面的2C个数,依次描述某个低级装备的
种类和需要的个数。

Output

  第一行包含一个整数S,表示最多可以提升多少点力量值。

Sample Input

10 59
5 A 3 6 1 9 2 10 1
1 B 5 3
1 B 4 3
1 B 2 3
8 A 3 2 1 3 1 7 1
1 B 5 3
5 B 3 3
15 A 3 1 1 5 1 4 1
1 B 3 5
1 B 4 3

Sample Output

33

HINT

Source

如果不是因为被盗号了我也不会做这种神题啊
树形DP神题 子节点转移的时候还要考虑对父亲的贡献
令f[i][j][k]表示以i为根的子树 贡献j个给父亲 共有k元的最大收益
枚举合成多少装备 g[i][j]表示考虑当前子树的前i个子树,有j元的最大收益 就可以转移了
然后写了半天 交一发 5s WA 调了一年居然还是WA
人眼fc一波 发现没啥差距 然后一怒之下粘标程 WA
1728031wxh0109101017Accepted47332 kb7996 msC++/Edit2297 B2016-12-06 21:43:56
1728009wxh0109101017Wrong_Answer47332 kb5140 msC++/Edit2235 B2016-12-06 21:30:42
1728001wxh0109101017Wrong_Answer47332 kb5156 msC++/Edit2291 B2016-12-06 21:26:50
1727986wxh0109101017Wrong_Answer61776 kb3916 msC++/Edit2573 B2016-12-06 21:20:07
1727984wxh0109101017Compile_ErrorkbmsC++/Edit2737 B2016-12-06 21:19:01
1727983wxh0109101017Wrong_Answer47188 kb5144 msC++/Edit2365 B2016-12-06 21:18:27
1727981wxh0109101017Wrong_Answer47332 kb5128 msC++/Edit1953 B2016-12-06 21:17:02
1727980wxh0109101017Wrong_Answer47328 kb52 msC++/Edit1951 B2016-12-06 21:16:42
1727769wxh0109101017Wrong_Answer47104 kb5220 msC++/Edit2047 B2016-12-06 20:00:46
1727730wxh0109101017Wrong_Answer47208 kb5160 msC++/Edit2047 B2016-12-06 19:46:37
1727723wxh0109101017Wrong_Answer47104 kb5156 msC++/Edit2045 B2016-12-06 19:43:53
然后看了看discuss ****还有没有任何高级物品的情况 写了个多重背包
http://blog.csdn.net/wxh010910/article/details/53500841
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include<bits/stdc++.h>  
  2.   
  3. using namespace std;  
  4.   
  5. const int maxn=55;  
  6. const int maxm=2020;  
  7. const int inf=1e9;  
  8.   
  9. int dp[maxn][105][maxm],f[maxn][maxm];  
  10.   
  11. int n,m,cnt,mx[maxn],cost[maxn],ans,v[maxn];  
  12.   
  13. int degree[maxn],head[maxn];  
  14.   
  15. struct edge  
  16. {  
  17.     int to,nxt,val;  
  18. }e[maxn*maxn];  
  19.   
  20. inline void addedge(int x,int y,int w)  
  21. {  
  22.     e[++cnt].to=y;  
  23.     e[cnt].nxt=head[x];  
  24.     head[x]=cnt;  
  25.     e[cnt].val=w;  
  26.     degree[y]++;  
  27. }  
  28.   
  29. char ch[2];  
  30.   
  31. void dfs(int x)  
  32. {  
  33.     if(!head[x])  
  34.     {  
  35.         mx[x]=min(mx[x],m/cost[x]);  
  36.         for(int i=0;i<=mx[x];i++)  
  37.             for(int j=i;j<=mx[x];j++)  
  38.                 dp[x][i][j*cost[x]]=(j-i)*v[x];  
  39.         return ;  
  40.     }  
  41.     mx[x]=inf;  
  42.     for(int i=head[x];i;i=e[i].nxt)  
  43.     {  
  44.         dfs(e[i].to);  
  45.         mx[x]=min(mx[x],mx[e[i].to]/e[i].val);  
  46.         cost[x]+=e[i].val*cost[e[i].to];  
  47.     }  
  48.     mx[x]=min(mx[x],m/cost[x]);  
  49.     memset(f,-0x3f3f3f3f,sizeof(f));  
  50.     f[0][0]=0;  
  51.     for(int c=mx[x];c>=0;c--)  
  52.     {  
  53.         int tot=0;  
  54.         for(int i=head[x];i;i=e[i].nxt)  
  55.         {  
  56.             tot++;  
  57.             for(int j=0;j<=m;j++)  
  58.                 for(int k=0;k<=j;k++)  
  59.                     f[tot][j]=max(f[tot][j],f[tot-1][j-k]+dp[e[i].to][c*e[i].val][k]);  
  60.         }  
  61.         for(int i=0;i<=c;i++)  
  62.             for(int j=0;j<=m;j++)  
  63.                 dp[x][i][j]=max(dp[x][i][j],v[x]*(c-i)+f[tot][j]);  
  64.     }  
  65. }  
  66.   
  67. int main()  
  68. {  
  69. //  freopen("A.in","r",stdin);  
  70.     memset(dp,-0x3f3f3f3f,sizeof(dp));  
  71.     scanf("%d%d",&n,&m);  
  72.     for(int i=1;i<=n;i++)  
  73.     {  
  74.         scanf("%d%s",&v[i],ch);  
  75.         if(ch[0]=='A')  
  76.         {  
  77.             int tot;  
  78.             scanf("%d",&tot);  
  79.             while(tot--)  
  80.             {  
  81.                 int to,val;  
  82.                 scanf("%d%d",&to,&val);  
  83.                 addedge(i,to,val);  
  84.             }  
  85.         }  
  86.         else scanf("%d%d",&cost[i],&mx[i]);  
  87.     }  
  88.     bool flag=false;  
  89.     for(int i=1;i<=n;i++) if(degree[i]) flag=true;  
  90.     if(flag)  
  91.     {  
  92.         for(int i=1;i<=n;i++)  
  93.             if(!degree[i])  
  94.             {  
  95.                 dfs(i);  
  96.                 for(int j=0;j<=mx[i];j++)  
  97.                     for(int k=0;k<=m;k++)  
  98.                         ans=max(ans,dp[i][j][k]);  
  99.             }  
  100.     }  
  101.     else  
  102.     {  
  103.         f[0][0]=0;  
  104.         for(int i=1;i<=n;i++)  
  105.             for(int k=0;k<=mx[i];k++)  
  106.                 for(int j=m;j>=k*cost[i];j--)  
  107.                     f[i][j]=max(f[i][j],f[i-1][j-k*cost[i]]+k*v[i]);  
  108.         for(int i=0;i<=m;i++) ans=max(ans,f[n][i]);  
  109.     }  
  110.     return printf("%d\n",ans),0;  
  111. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值