大厂笔试题
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

51 lines
2.1 KiB

/*
问题描述:
小美有一个长度为 n 的数组 a1,a2,.·,an ,他可以对数组进行如下操作:
1.删除第一个元素 a1,同时数组的长度减一,花费为x
2.删除整个数组,花费为k*MEX(a),其中MEX(a)表示a中未出现过的最小非负整数。例如[0,1,2,4]的 MEX为3。
小美想知道将 a 数组全部清空的最小代价是多少。
输入描述:
每个测试文件均包含多组测试数据。第一行输入一个整数T代表数据组数,每组测试数据描述如下第二行输入三个正整数:n,k,x
代表数组中的元素数量、删除整个数组的花费系数、删除单个元素的花费。第三行输入n个整数 a1, a2,...,an表示数组元素。
除此之外,保证所有的a之和不超过 2x105.
*/
/*
思路:动态规划+维护最小未出现的整数
dp[i]表示从i往后考虑的最小花费,最后的最小花费就是dp[0]和直接删除后续所有元素的最小值
对于删除后续所有的元素的选项,我们必须要知道mex是多少,可以在更新dp的过程中,用一个变量不断的更新当前的最小未出现的整数
虽然这里出现了两次循环的嵌套,但是并不会重置参数,因此复杂度是O(n)
*/
#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
using namespace std;
int main() {
int T;
cin >> T; // 读取测试数据组数
while (T--) {
long long n, k, x;
cin >> n >> k >> x;
vector<long long> a(n);
for (int i = 0; i < n; ++i) {
cin >> a[i];
}
// 动态规划数组dp[i]表示从i往后考虑的最小花费,最后最小花费就是dp[0]或者直接删除后续所有元素
vector<long long> dp(n + 1, LLONG_MAX);
dp[n] = 0;
int suffix_mex = 0;
set<int> vst;
for (int i = n-1; i >= 0; --i) {
vst.insert(a[i]);
while(vst.count(suffix_mex)){
suffix_mex++;
}
dp[i] = min(dp[i + 1] + x, k * suffix_mex);
}
// 输出最小花费
cout << dp[0] << endl;
}
return 0;
}