暗黑破坏神(diablo.pas)
无聊中的小x玩起了Diablo I...
游戏的主人公有n个魔法
每个魔法分为若干个等级,第i个魔法有p[i]个等级(不包括0)
每个魔法的每个等级都有一个效果值,一个j级的i种魔法的效果值为w[i][j]
魔法升一级需要一本相应的魔法书
购买魔法书需要金币,第i个魔法的魔法书价格为c[i]
而小x只有m个金币(好孩子不用修改器)
你的任务就是帮助小x决定如何购买魔法书才能使所有魔法的效果值之和最大
开始时所有魔法为0级 效果值为0
输入(diablo.in)
第一行 用空格隔开的两个整数n m
以下n行 描述n个魔法
第i+1行描述 第i个魔法 格式如下
c[i] p[i] w[i][1] w[i][2] ... w[i][p[i]]
输出(diablo.out)
第一行输出一个整数,即最大效果值。
以后n行输出你的方案:
第i+1行有一个整数v[i] 表示你决定把第i个魔法学到v[i]级
如果有多解 输出花费金币最少的一组
如果还多解 输出任意一组
样例
Input | Output |
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
保证输入数据和最终结果在longint范围内
一道sb的dp而已
f[i][j]表示前i种魔法用j金币的最大收益
然后变sb背包dp了
最后再保存一下f[i][j]从f[i-1][???]转移而来就可以打出方案
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<deque>
#include<set>
#include<map>
#include<ctime>
#define LL long long
#define inf 0x7ffffff
#define pa pair<int,int>
#define pi 3.1415926535897932384626433832795028841971
using namespace std;
pa f[110][510];
LL c[1000];
LL p[1000];
LL w[100][100];
LL zhan[1000];
LL n,m,top;
inline LL read()
{
LL x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int main()
{
freopen("diablo.in","r",stdin);
freopen("diablo.out","w",stdout);
n=read();m=read();
for (int i=1;i<=n;i++)
{
c[i]=read();
p[i]=read();
for (int j=1;j<=p[i];j++)w[i][j]=read();
}
for (int i=1;i<=n;i++)
for(int j=m;j>=0;j--)
{
f[i][j].first=f[i-1][j].first;
f[i][j].second=0;
for (int k=1;k<=min(j/c[i],p[i]);k++)
if (f[i-1][j-c[i]*k].first+w[i][k]>f[i][j].first)
{
f[i][j].first=f[i-1][j-c[i]*k].first+w[i][k];
f[i][j].second=k;
}
}
LL tot=-1,sav=-1,floor=n;
for(int i=1;i<=m;i++)
{
if (f[n][i].first>tot)
{
tot=f[n][i].first;
sav=i;
}
}
cout<<tot<<endl;
while (floor)
{
zhan[++top]=f[floor][sav].second;
sav-=f[floor][sav].second*c[floor];
floor--;
}
while (top)cout<<zhan[top--]<<endl;
}