2024年蓝桥杯 训练士兵 贪心算法

题目描述

在蓝桥王国中,有 n 名士兵,这些士兵需要接受一系列特殊的训练,以提升他们的战斗技能。对于第 i 名士兵来说,进行一次训练所需的成本为 pi 枚金币,而要想成为顶尖战士,他至少需要进行 ci 次训练。

为了确保训练的高效性,王国推出了一种组团训练的方案。该方案包含每位士兵所需的一次训练,且总共只需支付 S 枚金币(组团训练方案可以多次购买,即士兵可以进行多次组团训练)。

作为训练指挥官,请你计算出最少需要花费多少金币,才能使得所有的士兵都成为顶尖战士?

输入格式

输入的第一行包含两个整数 n 和 S ,用一个空格分隔,表示士兵的数量和进行一次组团训练所需的金币数。接下来的 n 行,每行包含两个整数 pi 和 ci ,用一个空格分隔,表示第 i 名士兵进行一次训练的金币成本和要成为顶尖战士所需的训练次数。

输出格式

输出一行包含一个整数,表示使所有士兵成为顶尖战士所需的最少金币数。

样例输入

复制

3 6
5 2
2 4
3 2

样例输出

复制

16

提示

【样例说明】

花费金币最少的训练方式为:进行 2 次组团训练,花费 2 × 6 = 12 枚金币,此时士兵 1, 3 已成为顶尖战士;再花费 4 枚金币,让士兵 2 进行两次训练,成为顶尖战士。总花费为 12 + 4 = 16。

【评测用例规模与约定】

对于 40% 的评测用例,1 ≤ n ≤ 103,1 ≤ pi, ci ≤ 105,1 ≤ S ≤ 107。

对于所有评测用例,1 ≤ n ≤ 105,1 ≤ pi, ci ≤ 106,1 ≤ S ≤ 1010。

千万注意数的范围!!long long int!!

代码1:

#include <bits/stdc++.h>
#define MX 100005
using namespace std;
struct soldier {  //士兵结构体
    long long int p;
    long long int c;
} d[MX];
bool cmp(soldier p,soldier q) {//将次数进行排序
    return p.c < q.c;
}
int main() {
    long long int n,s,cnt = 0,sum = 0;
    cin>>n>>s;
    for(long long int i = 1; i <= n; i++) {
        cin>>d[i].p>>d[i].c;
        sum += d[i].p;
    }
    sort(d+1,d+1+n,cmp);
    long long int ant = 0;
    for(int i = 1;i <= n;i++)
    {
        if(sum >= s)//贪心分情况讨论
        {
            cnt = cnt + (d[i].c - ant)*s;
            sum = sum - d[i].p;
            ant = ant + (d[i].c - ant);
        }
        else{
            cnt += (d[i].c - ant)*d[i].p;
        }
    }
    cout<<cnt<<endl;
    return 0;
}

代码2:

#include <bits/stdc++.h>
#define MX 100005
using namespace std;
struct soldier{
    long long int p;
    long long int c;
}d[MX];
bool cmp(soldier p,soldier q)
{
    return p.c < q.c;
}
int main() {
    long long int n,s,cnt = 0,sum = 0;//cnt记录花费,sum记录每个士兵训练一次的费用和 
    cin>>n>>s;
    for(long long int i = 1;i <= n;i++)
    {
        cin>>d[i].p>>d[i].c;
        sum += d[i].p;//费用和 
    } 
    sort(d+1,d+1+n,cmp);
    long long int ant = 1;//ant记录数组序号 
    while(sum >= s)
    {
        cnt = cnt + (d[ant].c - cnt);
        sum = sum - d[ant].p;
        ant++;
    }
    long long int t;
    t = cnt;
    cnt *= s;
    for(long long int i = ant;i <= n;i++)
    {
        cnt += (d[i].c - t)*d[i].p;//减去已经训练的次数 
    }
    cout<<cnt<<endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值