蓝桥杯备考冲刺必刷题(C++) | 3611 冒险者公会

学习C++从娃娃抓起!记录下蓝桥杯备考比赛学习过程中的题目,记录每一个瞬间。

附上汇总贴:蓝桥杯备考冲刺必刷题(C++) | 汇总-CSDN博客


【题目描述】
一个地区包含 n n n个村庄,每个村庄发布了一些委托任务,需要冒险者的帮助。
冒险者公会共有 m m m位冒险者。某位冒险者具有能力值 x i x_i xi,这表示他能够完成难度值小于等于 x x x的委托任务。每位冒险者最多只能出击一轮,在这一轮中,他们可以不重复地通过若干个村庄。
当一名冒险者路过一个村庄时,他最多只能完成该村庄的一个委托任务,且这个委托的难度不能超过冒险者的能力值。冒险者也可以选择在路过一些村庄时不完成任何委托任务。同样的,每个委托任务只需要被完成一次。
无论冒险者完成多少任务,这名冒险者出击一轮的代价都等同于冒险者的能力值。
现在的目标是确定一种冒险者的出勤方案,以使得完成所有村庄的委托任务的总代价最小。
【输入】
第一行输入两个整数 m m m n n n,分别表示冒险者的数量和村庄的数量, 0 < m , n ≤ 1 0 3 0\lt m,n\le 10^3 0<m,n103
第二行 m m m个整数 x 1 , x 2 , … x i , … x m x_1,x_2,\dots x_i,\dots x_m x1,x2,xi,xm,代表每位冒险者的能力值, 0 < x i ≤ 1 0 3 0\lt x_i\le 10^3 0<xi103
接下来 n n n行,每行代表一个村庄,每行第一个整数k表示该村庄的委托数量,此后 k k k个不大于 1 0 3 10^3 103的正整数表示该村庄的每个委托任务的难度值, 0 < k ≤ 1 0 3 0\lt k\le 10^3 0<k103
【输出】
在一行中输出一个整数,表示完成所有委托所需的最小总代价。如果不能完成所有的委托,则直接输出 − 1 -1 1
【输入样例】

3 4
2 9 6
2 3 7
1 5
3 2 2 3
3 1 1 1

【输出样例】

17

【代码详解】
[图片]

#include <bits/stdc++.h>
using namespace std;
#define ll long long
int m, n, k, unit;
int level[1005], city[1005][1005], mx[1005];
int main()
{
    cin >> m >> n;
    for (int i=1; i<=m; i++) {
        cin >> level[i];
    }
    sort(level+1, level+m+1);  // 冒险者按照能力从小到大排序
    for (int i=1; i<=n; i++) {
        cin >> k;
        if (k>m) {  // 如果委托比冒险者人数还多,那么一定不能完成
            cout << -1 << endl;
            return 0;
        }
        for (int j=1; j<=k; j++) {
            cin >> city[i][j];
        }
        sort(city[i]+1, city[i]+m+1);  // 每个村庄的委托任务从小到大排序
    }
    for (int i=1; i<=m; i++) {  // 每一轮都完成每个村庄里最难的一个任务,记录每一轮的最难任务的代价
        unit = city[1][i];  // 定义一个临时值
        for (int j=1; j<=n; j++) {  // 遍历n个村庄
            if (unit < city[j][i]) {  // 擂台法,求得每个村庄的最难任务
                unit = city[j][i];
            }
        }
        mx[i] = unit;
    }
    int mani = 1, cityi=1;
    ll ans = 0;
    while (cityi<=m && mx[cityi]==0) {  // 得到cityi的起始值(不为0)
        cityi++;
    }
    while (mani<=m && cityi<=m) {  // 双指针查看是否能够完成所有委托
        if (mx[cityi]<=level[mani]) {  // 如果某个人能完成这个村庄最难的任务,这个村庄的任务就肯定能全部完成(因为后面的人能力都超过该人)
            cityi++;  // 村庄数自增1
            ans += level[mani];  // 加上这个冒险者的能力值
        }
        mani++;  // 不管这个人能否完成这个村庄的任务,都换下个人(如果没完成,mani不增加)
    }
    if (cityi==m+1) {  // 如果完成所有委托则输出总代价
        cout << ans << endl;
    } else {
        cout << -1 << endl;
    }
    return 0;
}

【运行结果】

3 4
2 9 6
2 3 7
1 5
3 2 2 3
3 1 1 1
17
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值