训练士兵 | 第十五届蓝桥杯省赛C++A组

在蓝桥王国中,有 nn 名士兵,这些士兵需要接受一系列特殊的训练,以提升他们的战斗技能。

对于第 ii 名士兵来说,进行一次训练所需的成本为 pipi 枚金币,而要想成为顶尖战士,他至少需要进行 cici 次训练。

为了确保训练的高效性,王国推出了一种组团训练的方案。

该方案包含每位士兵所需的一次训练,且总共只需支付 SS 枚金币(组团训练方案可以多次购买,即士兵可以进行多次组团训练)。

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

输入格式

第一行包含两个整数 nn 和 SS,表示士兵的数量和进行一次组团训练所需的金币数。

接下来的 nn 行,每行包含两个整数 pipi 和 cici,表示第 ii 名士兵进行一次训练的金币成本和要成为顶尖战士所需的训练次数。

输出格式

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

数据范围

对于 40%40% 的测评用例,1≤n≤1031≤n≤103,1≤pi,ci≤1051≤pi,ci≤105,1≤S≤1071≤S≤107。
对于所有测评用例,1≤n≤1051≤n≤105,1≤pi,ci≤1061≤pi,ci≤106,1≤S≤10101≤S≤1010。

输入样例:
3 6
5 2
2 4
3 2
输出样例:
16
样例解释

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

总花费为 12+4=1612+4=16。

题解:

        发现,当当前训练士兵的训练价格之和大于团体训练的价格时,就采用团体训练,相反,则采用单独训练,这是训练一次的情况。

        预处理所有士兵总训练价格sum。

        于是按训练次数升序排序,从前往后遍历累加训练价格sum2,当sum-sum2<price,即剩下的还需训练的士兵的训练价格之和小于团体,采用单独训练,即退出循环,遍历后续价格*次数的和,再与团体次数求和,升序排序的意义就是找到团体的次数。

        特殊情况:当团体价格过低,每一个士兵训练价格都大于团体。即全部采用团体。

代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iomanip>
#include<queue>
#include<stack>
#include<vector>
#include<unordered_set>
#include<unordered_map>
#include<map>
#include<set>
using namespace std;
typedef long long int ll;
const int INF=1e16;

long long int n,price;
struct node{
    long long int times;
    long long int princes;
};
vector<node> vt;
long long int sum=0;
long long int ans=0;
long long int sum_times=0;
long long int sum2=0;

int cmp(node a,node b){
    return a.times<b.times;
}

void solve(){
    cin >> n >> price;
    //vector<long long int> pre;
    //pre.push_back(0);
    for(int i=0;i<n;i++){
        long long int p,t;
        cin >> p >> t;
        node no;
        no.princes=p;
        no.times=t;
        vt.push_back(no);
        sum+=p;
        //sum_times+=t;
        //pre.push_back(p*t+pre[i]);
    }
    sort(vt.begin(),vt.end(),cmp);
    //cout << sum << "\n";
    //cout << vt[n-1].times << "\n";
    //cout << "Yes";
    /*
    for(int i=0;i<n;i++){
        cout << vt[i].princes << " " << vt[i].times << "\n";
    }
    */
    /*
    for(int i=0;i<=n;i++){
        cout << pre[i] << "\n";
    }
    */
    for(int i=0;i<n;i++){
        if(sum-sum2<price){
            ans+=(vt[i-1].times*price);
            //cout << ans << "\n";
            //ans+=(pre[pre.size()-1]-pre[i]);
            for(int j=i;j<n;j++){
                ans+=(vt[j].princes*(vt[j].times-vt[i-1].times));
            }
            break;
        }
        else if(i==n-1){
            ans=vt[n-1].times*price;
            break;
        }
        sum2+=vt[i].princes;
    }
    cout << ans;
}

int main(){
    solve();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值