技能树 题解
题目
玩过
D
i
a
b
l
o
Diablo
Diablo的人对技能树一定是很熟悉的。一颗技能树的每个结点都是一项技能,要学会这项技能则需要耗费一定的技能点数。只有学会了某一项技能以后,才能继续学习它的后继技能。每项技能又有着不同的级别,级别越高效果越好,而技能的升级也是需要 耗费技能点数的。
有个玩家积攒了一定的技能点数,他想尽可能地利用这些技能点数来达到最好的效果。因此他给所有的级别都打上了分,他认为效果越好的分数也越高。现在他要你帮忙寻找一个分配技能点数的方案,使得分数总和最高。
输入
第一行是一个整数 n n n(1<= n n n<=20),表示所有不同技能的总数。接下来依次给出 n n n个不同技能的详细情况。每个技能描述包括5行,第一行是该技能的名称,第2行是该技能在技能树中父技能的名称,为空则表示该技能不需要任何的先修技能便能学习。第3行是一个整数 L L L(1<= L L L<=20),表示这项技能所能拥有的最高级别。第4行共有 L L L个整数,其中第 I I I个整数表示从地I-1级升到第 I I I级所需要的技能点数(0级表示没有学习过)。第5行包括 L L L个整数,其中第 I I I个整数表示从第 I I I-1级升级到第I级的效果评分,分数不超过20。在技能描述之后,共有两行,第1行是一个整数 P P P,表示目前所拥有的技能点数。接下来1行是 N N N个整数,依次表示角色当前习得的技能级别,0表示还未学习。这里不会出现非法情况。
输出
S,表示最佳分配方案所得的分数总和。
样例
input
3
Freezing Arrow
Ice Arrow
3
3 3 3
15 4 6
Ice Arrow
Cold Arrow
2
4 3
10 17
Cold Arrow
3
3 3 2
15 5 2
10
0 0 1
output
42
解题思路
f[i][j]意思为学到第i个技能花了j个技能点数得到的价值
分两种情况思考
第一种:
原先有等级,不升级
if (d[h[i].to])
{
for (int j=0;j<=r;j++)
f[h[i].to][j]=f[x][j];
dfs(h[i].to,r);
for (int j=0;j<=r;j++)
f[x][j]=max(f[x][j],f[h[i].to][j]);
}
第二种:
升级它
for (int j=d[h[i].to]+1;j<=l[h[i].to];j++)
{
g1+=l1[h[i].to][j];
g2+=l2[h[i].to][j];
if (r-g1<0) continue;
for (int k=0;k<=r-g1;k++)
f[h[i].to][k]=tm[k];
dfs(h[i].to,r-g1);
for (int k=g1;k<=r;k++)
f[x][k]=max(f[x][k],f[h[i].to][k-g1]+g2);
}
代码
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
struct hhx{
int to,next;
}h[500200];
int n,m,a[1020],t,tt,l[1020],l1[1020][1020],l2[1020][1020],head[1020];
int f[1020][1020],d[1020];
string s,su[1020];
int find(string x)
{
for (int i=1;i<=t;i++) //找到它在数组里是第几位
if (x==su[i])
return i;
su[++t]=x; //没出现过,加入数组
return t;
}
void add(int x,int y) //连接
{
h[++tt].to=y;
h[tt].next=head[x];
head[x]=tt;
}
void dfs(int x,int r)
{
int tm[120];
if (r<0) return;
for (int i=head[x];i;i=h[i].next)
{
for (int j=0;j<=r;j++)
tm[j]=f[x][j];
if (d[h[i].to]) //不升级
{
for (int j=0;j<=r;j++)
f[h[i].to][j]=f[x][j];
dfs(h[i].to,r);
for (int j=0;j<=r;j++)
f[x][j]=max(f[x][j],f[h[i].to][j]);
}
int g1=0,g2=0;
for (int j=d[h[i].to]+1;j<=l[h[i].to];j++) //升级
{
g1+=l1[h[i].to][j];
g2+=l2[h[i].to][j];
if (r-g1<0) continue;
for (int k=0;k<=r-g1;k++)
f[h[i].to][k]=tm[k];
dfs(h[i].to,r-g1);
for (int k=g1;k<=r;k++)
f[x][k]=max(f[x][k],f[h[i].to][k-g1]+g2);
}
}
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
getline(cin,s);
getline(cin,s);
a[i]=find(s);
getline(cin,s);
int y=0;
if (s!="")
y=find(s);
add(y,a[i]);
scanf("%d",&l[a[i]]);
for (int j=1;j<=l[a[i]];j++) scanf("%d",&l1[a[i]][j]);
for (int j=1;j<=l[a[i]];j++) scanf("%d",&l2[a[i]][j]);
}
scanf("%d",&m);
for (int i=1;i<=n;i++)
scanf("%d",&d[a[i]]);
dfs(0,m);
printf("%d",f[0][m]);
}