题目:冒险者公会(蓝桥OJ 3611)

问题描述:


解题思路:

        官方:

        注意点:

               在前期的排序操作,因为需要找到如样例所示的每轮最大,因此我们需要用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;
}

知识点:贪心

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值