学习C++从娃娃抓起!记录下在学而思小猴编程学习过程中的题目,记录每一个瞬间。侵权即删,谢谢支持!
附上汇总贴:小猴编程C++ | 汇总-CSDN博客
【题目描述】
小猴在玩一个垃圾游戏,他当前的目标是提升角色的等级,从第
k
k
k级升级到
k
+
1
k+1
k+1级需要
e
k
e_k
ek点经验值。这个游戏通过消耗经验值素材来升级,共有
m
m
m种经验值素材,第
i
i
i种素材能够增加
p
i
p_i
pi点经验值,需要花费
t
i
t_i
ti秒才能得到
1
1
1个。同种经验值素材可以反复获得。
这个游戏垃圾的地方在于:经验值素材只能整个使用,于是可能发生使用素材增加的经验值超过升级所需经验值的可能,此时超过的部分就直接消失了,不会继承到下一级。例如:从
1
1
1级升级到
2
2
2级需要
100
100
100点经验值,
1
1
1个经验值s素材可以增加
75
75
75点经验,小猴只能使用
2
2
2个素材,增加
150
150
150点经验值,升到
2
2
2级,多出的
50
50
50点会浪费掉。
小猴想要从
1
1
1级升到
n
n
n级,至少需要多少秒?
【输入】
第
1
1
1行,
2
2
2个正整数
n
,
m
n,m
n,m。
第
2
2
2行,
n
−
1
n-1
n−1个正整数
e
1
,
e
2
,
…
,
e
n
−
1
e_1,e_2,\dots,e_{n-1}
e1,e2,…,en−1,表示从
1
,
2
,
…
,
n
−
1
1,2,\dots,n-1
1,2,…,n−1升到下一级需要的经验值。
第
3
3
3行,
m
m
m个正整数
p
1
,
p
2
,
…
,
p
m
p_1,p_2,\dots,p_m
p1,p2,…,pm。
第
4
4
4行,
m
m
m个正整数
t
1
,
t
2
,
…
,
t
m
t_1,t_2,\dots,t_m
t1,t2,…,tm。
【输出】
1
1
1个整数,升级到
n
n
n级最少需要的时间。
【输入样例】
4 3
10 30 49
2 8 16
1 3 5
【输出样例】
30
【代码详解】
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5+5;
const int M = 105;
int n, m, e[N], p[M], t[M], dp[51005], mint[51005];
int main()
{
cin >> n >> m;
for (int i=1; i<n; i++) cin >> e[i]; // 输入e[i]
for (int i=1; i<=m; i++) cin >> p[i]; // 输入p[i]
for (int i=1; i<=m; i++) cin >> t[i]; // 输入t[i]
memset(dp, 0x3f, sizeof(dp)); // 求恰好j经验的最小时间,所以初始设为最大值
dp[0] = 0; // 起始dp[0]时需要0时间
for (int i=1; i<=m; i++) { // 全完背包,i表示m中素材
for (int j=p[i]; j<=51000; j++) { // j表示恰好获得j经验
dp[j] = min(dp[j], dp[j-p[i]]+t[i]); // dp[j]为上一个素材的时间dp[j],或取当前素材i的时间dp[j-p[i]]+t[i],两者最小值
}
}
mint[51001] = 0x3f3f3f3f; // mint表示至少获得j经验的最小时间,初始设为无穷大
for (int i=51000; i>=1; i--) { // 从51000-1
mint[i] = min(mint[i+1], dp[i]); // 再多1个单位经验的最小值mint[i+1],以及恰好i经验的最小值dp[i],两者取最小值(mint中的值肯定是大于i,或为2*i、i+1等,但因为求最小,所以i+1即可)
}
LL ans = 0; // e[i]相加会超INT类型最大值,所以为long long类型
for (int i=1; i<n; i++) ans += mint[e[i]]; // 计算每个经验的最小时间之和
cout << ans << endl; // 输出结果
return 0;
}
【运行结果】
4 3
10 30 49
2 8 16
1 3 5
30