样例输入
3 4
2 9 6
2 3 7
1 5
3 2 2 3
3 1 1 1
样例输出
17
样例说明
一种可行的代价最小的执行方案如下。
第一轮 | 第二轮 | 第三轮 | |
---|---|---|---|
出勤冒险者能力值 | 9 | 6 | 2 |
村庄1委托难度值 | 7 | 3 | \ |
村庄2委托难度值 | 5 | \ | \ |
村庄3委托难度值 | 3 | 2 | 2 |
村庄4委托难度值 | 1 | 1 | 1 |
将三轮任务的代价求和 9+6+2 得到答案 17。
- 村庄的委托任务数量可能大于冒险者的数量,这个时候要返回-1
- 要记录全部村庄的最大委托任务数量,因为村庄的最大委托任务数量可能小于冒险者的数量,这个时候剩下的冒险者的能力值就不用再加上了
- 要把村庄的委托任务难度进行排序,把难的都排在前面,然后竖着记录下当前列的最难委托任务,只要冒险者把这个委托任务完成了,就能完成该列的全部任务
- 每次执行完任务的冒险者都要删掉,因为每位冒险者只能执行一次任务,要避免同一个冒险者重复执行任务
注意: 不能单独的把冒险者也从大到小排序,然后从最大的冒险者和该列的最大委托任务难度进行比较这种方法,这样的方法出来的冒险者可能不是能完成任务的最小代价(即冒险的能力值不是最小的)要通过查找刚好能大于或者等于该列的最大委托任务难度的冒险者
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e3+5;
int max_power[N];
vector<vector<int>> a(N);
multiset<int> x; //用于存储一组整数。它允许重复的元素,并且元素会自动按照升序排列。
bool cmp(int b,int c){
return b>c;
}
int main(){
int m,n,max_num=-1;
ll sum=0;
cin>>m>>n;
for(int i=1;i<=m;i++){ //输入冒险者的参数
int j;
cin>>j;
x.insert(j);
}
for(int i=1;i<=n;i++){ //输入村庄
int k;
cin>>k;
max_num=max(max_num,k); //记录村庄的最大委托任务数量
if(k>m){
cout<<"-1";
return 0;
}
for(int j=1;j<=k;j++){ //输入单个村庄的信息
int g;
cin>>g;
a[i].push_back(g);
}
sort(a[i].begin(),a[i].end(),cmp); //从大到小排序
}
for(int i=1;i<=max_num;i++){ //竖列记录最大的村庄委托任务
for(int j=1;j<=n;j++){
if(a[j].empty()) continue;
max_power[i]=max(max_power[i],a[j][0]);
a[j].erase(a[j].begin());
}
}
for(int i=1;i<=max_num;i++){
if(x.lower_bound(max_power[i])!=x.end()){ //判断能够满足的最大村庄委托难度
sum+=*x.lower_bound(max_power[i]);
x.erase(x.lower_bound(max_power[i]));
}
else{
cout<<"-1";
return 0;
}
}
cout<<sum;
return 0;
}