问题 R: 暗黑破坏神
时间限制: 1 Sec 内存限制: 128 MB
提交: 61 解决: 12
[提交][状态][讨论版][命题人: cbc]
题目描述
无聊中的小x玩起了Diablo III...
游戏的主人公有n个魔法
每个魔法分为若干个等级,第i个魔法有p[i]个等级(不包括0)
每个魔法的每个等级都有一个效果值,一个j级的i种魔法的效果值为w[i][j]
魔法升一级需要一本相应的魔法书
购买魔法书需要金币,第i个魔法的魔法书价格为c[i]
而小x只有m个金币(好孩子不用修改器)
你的任务就是帮助小x决定如何购买魔法书才能使所有魔法的效果值之和最大
开始时所有魔法为0级 效果值为0
输入
第1行 用空格隔开的两个整数n和m个金币
以下n行 描述n个魔法
第i+1行描述 第i个魔法 格式如下
c[i] p[i] w[i][1] w[i][2] ... w[i][p[i]]
输出
第1行输出一个整数,即最大效果值。
第2-n+1行输出购买魔法书的最优选择。
样例输入
3 10
1 3 1 2 2
2 3 2 4 6
3 3 2 1 10
样例输出
11
1
0
3
提示
0< n< =100,0< m <=500,0 < p[i] <= 50,0 < c[i] <=10
虽然没验证,但是应该是对的,将原来错误%9的进行修改
原来错在同样最大效果值下,没有输出消耗金币最少的路径
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
long long c[101],p[101][55],f[505]={0},x[505][505];
int main()
{
int n,m;
int i,j,k;
cin>>n>>m;
memset(x,0,sizeof(x));
memset(f,0,sizeof(f));
for(i=1;i<=n;i++)
{
scanf("%lld %lld",&c[i],&p[i][0]);
for(j=1;j<=p[i][0];j++)
scanf("%lld",&p[i][j]);
}
for(i=1;i<=n;i++)
{
for(j=m;j>=0;j--)
{
for(k=0;k<=p[i][0];k++)
{
int cot;
if(k==0) cot=0;
else cot=p[i][k];
if(j-k*c[i]<0) break;
else
{
if(f[j]<f[j-k*c[i]]+cot)
{
f[j]=f[j-k*c[i]]+cot;
x[i][j]=k;
}
}
}
}
}
cout<<f[m]<<"\n";
long long p=m,ans[505];
memset(ans,0,sizeof(ans));
for(i=m-1;i>=0;i--)//循环可以找到最大效果值下,消耗金币最少的路径
if(f[i]==f[p]&&i<p)
p=i;
for(i=n;i;--i)
{
ans[i]=x[i][p];
p-=c[i]*ans[i];
}
for(i=1;i<=n;i++)
printf("%lld\n",ans[i]);
return 0;
}
/*
3 10
9 1 1
8 1 1
7 1 1
*/