问题描述:
解题思路:
官方:
注意点:
在前期的排序操作,因为需要找到如样例所示的每轮最大,因此我们需要用0代替没有的委托(即样例斜杠)。如何用0代替:将村庄委托数量默认为勇者数量(前期已经考虑了勇者数量小于委托,这样没问题)。样例由大到小,而我们的代码由小到大。
下图为勇者数量为4和3的情况:#i 表示每轮,mx 表示每轮的最大值
题解:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int m, n;
cin >> m >> n; // 输入冒险者数量和村庄数量
vector<int> level(m);
for (int i = 0; i < m; i++)
cin >> level[i]; // 输入冒险者能力值
sort(level.begin(), level.end()); // 按从小到大排序
vector<vector<int> > city(n, vector<int>(m, 0)); // vector<int>(m,0)表示初始为m个0,你仍可输入超过m个数。该行代码用于补充0
int k;
for (int i = 0; i < n; i++) {
cin >> k; // 输入委托个数
if (k > m) { // 如果委托比冒险者人数还多,那么一定不能完成
cout << -1 << endl;
return 0;
}
for (int j = 0; j < k; j++)
cin >> city[i][j]; // 输入每个委托难度值
sort(city[i].begin(), city[i].end()); // 按从小到大排序
}
vector<int> mx(m);
int unit;
for (int i = 0; i < m; i++) { // 每一轮都完成每个村里最难的一个任务,记录每一轮的最难任务的代价
unit = city[0][i];
for (int j = 0; j < n; j++)
if (unit < city[j][i])
unit = city[j][i];
mx[i] = unit;
}
int mani = 0, cityi = 0; // 两指针:mani指向勇者,cityi指向第几轮
ll ans = 0;
while(cityi < m && mx[cityi] == 0)
cityi++; // 跳过每个村庄委托全是0的一轮,通过++将指针指向不全为0的一轮
while (mani < m && cityi < m) { // 双指针查看是否能够完成所有委托(由小到大依次比较)
if (mx[cityi] <= level[mani]) {
cityi++;
ans += level[mani];
}
mani++;
}
if (cityi == m) // 如果完成所有委托则输出总代价(轮数=村庄数,全为0也算一轮)
cout << ans << endl;
else // 如果所有冒险者都已派遣但仍有委托没有完成则失败
cout << -1;
return 0;
}
知识点:贪心