组装电脑
Problem Description
小红准备买一些零件来组装电脑。已知电脑一共有n个零件,每个零件有若干个型号。小红现在知道了每个型号的对应价格 a i a_{i} ai,以及性能 v i v_{i} vi。小红需要每个零件选择一个型号,在总价格不超过x元的前提下,最终的总性能尽可能大。你能帮帮她吗?
input
第一行输入两个正整数n和x,代表电脑的零件数量以及小红最大的预算。 接下来的3∗n行,每三行用来描述一个零件的不同型号的价格和性能。
对于每个零件,第一行输入一个正数m,代表该零件有多少种型号。 1 ≤ n , m ≤ 40 , 1 ≤ a i , v i , x ≤ 1 0 9 1≤n,m≤40,1≤a_i ,v_i ,x≤10^9 1≤n,m≤40,1≤ai,vi,x≤109
保证所有m之和不超过40,即所有零件的型号数保证所有m之和不超过40,即所有零件的型号数量之和不超过40种。ouput
如果无法完成组装,则直接输出-1。否则输出一个正整数,代表最终最大的性能。
Sample Input
2 4
2
1 2
3 5
3
3 2 3
5 6 7文章来源:https://www.toymoban.com/news/detail-493921.htmlSample Output
11文章来源地址https://www.toymoban.com/news/detail-493921.html
题目类型、难度、来源
- 类型:动态规划
- 难度:中等
- 来源:蚂蚁春招-2023.3.16-组装电脑
总体思路:
- 使用动态规划。 d p [ i ] [ j ] dp[i][j] dp[i][j]表示买前i个零件,共花了j元(i从1算起,i=0表示没有零件)获得的最大性能。 c o s t [ i ] , p e r f [ i ] cost[i],perf[i] cost[i],perf[i]分别表示第i个零件的价格和性能。
- 边界条件: d p [ 0 ] [ 0 ] = 0 dp[0][0] = 0 dp[0][0]=0,表示买前0个零件,共花了0元,性能是0。
- 状态转移方程: d p [ i ] [ j ] = m a x { d p [ i − 1 ] [ j − c o s t [ 0 ] ] + p e r f [ 0 ] , d p [ i − 1 ] [ j − c o s t [ 1 ] ] + p e r f [ 1 ] , . . . } dp[i][j]=max{\{dp[i-1][j-cost[0]]+perf[0], dp[i-1][j-cost[1]]+perf[1], ...\}} dp[i][j]=max{dp[i−1][j−cost[0]]+perf[0],dp[i−1][j−cost[1]]+perf[1],...}
- 这个方程比较难计算,我们可以反过来思考。
- 可以使用 d p [ i ] [ j ] dp[i][j] dp[i][j]去更新 d p [ i + 1 ] [ j + c o s t [ 0 ] ] dp[i+1][j+cost[0]] dp[i+1][j+cost[0]]、 d p [ i + 1 ] [ j + c o s t [ 1 ] ] dp[i+1][j+cost[1]] dp[i+1][j+cost[1]]等等。
- 具体的:
d
p
[
i
+
1
]
[
j
+
c
o
s
t
[
0
]
]
=
m
a
x
(
d
p
[
i
+
1
]
[
j
+
c
o
s
t
[
0
]
]
,
d
p
[
i
]
[
j
]
+
p
e
r
f
[
0
]
)
dp[i+1][j+cost[0]]=max(dp[i+1][j+cost[0]], dp[i][j]+perf[0])
dp[i+1][j+cost[0]]=max(dp[i+1][j+cost[0]],dp[i][j]+perf[0])
- 这个公式需要不断被刷新,因为 d p [ i + 1 ] [ j + c o s t [ 0 ] ] dp[i+1][j+cost[0]] dp[i+1][j+cost[0]]的值和多个dp数组值有关。
- 完成上述推理后,我们开始写代码,却发现x的只最大可以达到 1 0 9 10^9 109,如果使用传统方法做动态规划,这肯定就不行了,因为开不了那么大的数组。为了解决这个问题,我们可以使用map充当数组。
AC代码
#include <iostream>
#include <algorithm>
#include <map>
using namespace std;
int main(){
int n, x;
cin >> n >> x;
int **cost = new int*[n];
int **perf = new int*[n];
int *comp_nums = new int[n];
for (int t = 0; t < n; t++){
cin >> comp_nums[t];
cost[t] = new int[comp_nums[t]];
perf[t] = new int[comp_nums[t]];
for (int i = 0; i < comp_nums[t]; i++){
cin >> cost[t][i];
}
for (int i = 0; i < comp_nums[t]; i++){
cin >> perf[t][i];
}
}
map<long long, long long> dp[45];
dp[0][0] = 0;
long long max_perf = -1;
for (long long t = 0; t < n; t++){
for (auto iter = dp[t].begin(); iter != dp[t].end(); iter++){
long long dp_cost = iter->first;
long long dp_perf = iter->second;
for (long long i = 0; i < comp_nums[t]; i++){
if (dp_cost+cost[t][i] <= x){
dp[t+1][dp_cost+cost[t][i]] = max(dp[t+1][dp_cost+cost[t][i]], dp_perf+perf[t][i]);
if ((t+1 == n) && (dp[t+1][dp_cost+cost[t][i]] > max_perf)){
max_perf = dp[t+1][dp_cost+cost[t][i]];
}
}
}
}
}
cout << max_perf;
return 0;
}
- 更多大厂真题可以看:2023实习、秋招互联网大厂技术岗算法真题-刷题(持续更新)
到了这里,关于蚂蚁春招-2023.3.16-组装电脑-中等的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!