1 条题解
-
0
自动搬运
来自洛谷,原作者为

ysner
这个家伙不懒,但也什么都没有留下搬运于
2025-08-24 21:31:10,当前版本为作者最后更新于2018-02-08 08:44:04,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
这题有点难想啊,看了一个小时才有思路,也许是我太弱了首先,这道题肯定是DP。
其次,分析样例,会发现题目有个隐藏条件:只能用开局的V元钱买入药品。
经过对题面的研究,我们可以发现,那一长串药物合成关系实在不好在DP中用上,我们应当把他们变得易于处理,如用ans[i][j]表示第i个物品在用j次魔法的前提下所需最小代价(即原材料价钱)。
但ans[i][j]不太好直接求,我们可以再开一个DP数组ant[i][j]表示前i个药品在使用j次魔法前提下合成所需最小代价。这样就能通过ant[i][j]将合成原材料和合成品联系起来,顾及到 需要魔法总次数 等诸多因素。
有了以上作为基础,DP处理出结果就方便多了。设DP[i][j]为使用第i次魔法,使用j块钱所获最大利润,依此列式即可。
还有,一种药品可能有多种合成方式。
我因把药品与合成关系一一对应WA了一版。#include<bits/stdc++.h> #define ll long long #define re register #define il inline #define fp(i,a,b) for(re int i=a;i<=b;i++) #define fq(i,a,b) for(re int i=a;i>=b;i--) using namespace std; const int N=300; int m,n,q,k,s[N],h[N],op,ans[N][N],dp[N][1005],ant[N][50]; struct line { int a,l,p[N]; }e[N]; il int gi() { re int x=0,t=1; re char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-') ch=getchar(); if(ch=='-') t=-1,ch=getchar(); while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar(); return x*t; } int main() { n=gi();m=gi();q=gi();k=gi(); fp(i,1,n) s[i]=gi(),h[i]=gi(); fp(i,1,m) { e[i].a=gi();e[i].l=gi(); fp(j,1,e[i].l) e[i].p[j]=gi(); } fp(i,1,n) fp(j,0,k) ans[i][j]=s[i]; fp(o,1,k) fp(i,1,m) { fp(j,1,e[i].l)//枚举一合成关系中的物品 { fp(t,0,o-1)//总魔法次数 { ant[j][t]=1e9; fp(tt,0,t)//当前物品使用魔法次数 ant[j][t]=min(ant[j][t],ant[j-1][t-tt]+ans[e[i].p[j]][tt]); } } ans[e[i].a][o]=min(ans[e[i].a][o],ant[e[i].l][o-1]); }//处理药品合成信息 fp(i,1,n) fp(j,0,k) fp(t,0,k-j)//枚举当前物品使用魔法次数 fp(s,0,q-ans[i][j])//枚举使用钱数 dp[j+t][s+ans[i][j]]=max(dp[j+t][s+ans[i][j]],dp[t][s]+h[i]-ans[i][j]);//简单DP求解 printf("%d\n",dp[k][q]); return 0; }
- 1
信息
- ID
- 829
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者