思路:题目的花费就是我们要去除数组中所有0的最小花费,找出最初的mex使其等于mexx,从mexx往下一层一层算,dp[i]表示使mex达到i花费的最小值,
转移方程是:
dp[i]=min(从mexx直接到i的花费,从mexx到j再到i的花费)
记得用map存出现次数,不然爆数组
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e9 + 5;
int gcd(int a, int b) {
return b ? gcd(b, a % b) : a;
}
void solve(){
int n; cin >> n;
vector<int>a(n);
map<int, int>cnt;
for (int i = 0; i < n; i++) {
cin >> a[i];
cnt[a[i]]++;
}
int mexx = 0;
while (cnt[mexx])mexx++;
if (cnt[0] <= 0) { cout << 0 << '\n'; return; }
int dp[5005]={ };
for (int i = mexx - 1; i >= 0; i--) {
dp[i] = (cnt[i] - 1) * mexx + i;
for (int j = i + 1; j < mexx; j++) {
dp[i] = min(dp[i], dp[j] + (cnt[i] - 1) * j + i);
}
}
cout << dp[0] << '\n';
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
std::cout.tie(0);
int t = 1;
cin >> t;
while (t--)
solve();
return 0;
}