noip2018模拟题(类背包+贪心)

 

  1. 马拉松冰球赛

(marathon.pas/c/cpp)

 

马拉松冰球锦标赛的日子就要到了。正如马拉松冰球比赛中经常出现的那样,比赛时间 M 分钟。和常规的冰球比赛一样,在每一给定时刻,场上两队各有 6 球员。然而,一场马拉松冰球比赛可以持续很长时间,所以教练带了一群球员,这样当球员们累了的时候,   他们可以进行替换。

其中一个名为 Ante 的教练是我们故事的主角。Ante 带了 N 个球员参加比赛。对于每一个球员,他知道两个参数:球员的能力值 K 和耐力值 I耐力值是指球员参赛的最大总时间。假设一个球员先参加 X 分钟,然后休息,再参加 Y 分钟,他的总参赛时间就是 X+Y。当一个球员的总参赛时间等于其耐力值的时候,他就会感到疲惫,不能继续参赛,所以这个时候,   就需要其他人来代替他,否则他会晕倒在赛场上,最终被送进医院(马拉松冰球是一个危险的项目)。

在一个给定时刻,队伍的能力值就是当前参赛队员能力值的总和。Ante 并不是一个伟大的教练,所以他要求你拿出最初的六名球员和替补球员的方案,以便他能达到每个时刻队   伍能力值总和的可能的最大值 Z。保证一定能找到一种方案,使得每个时刻场上都有 6 名球员。

举个例子,假设比赛时间为 3 分钟,而第一分钟队伍的能力值是 15,第二分钟队伍的能力值是 12,第三分钟队伍的能力值是 14Z 就等于 15+12+14=41

请注意:在马拉松冰球赛中是没有守门员的,因为比赛必须有趣。

 

【输入】

第一行输入两个正整数 M N(1≤M≤500 000,6≤N≤500000),分别表示比赛的持续时间(以分钟为单位),和 Ante 带领的球员数量。

接下来 N 行,每行两个正整数 K I(1≤K≤100 000,1≤I≤M),表示每个球员的能力值和耐力值。

球员按照输入顺序,从 1 N 编号。

 

【输出】

第一行包含题目要求的可能的最大值 Z

 

【输入输出样例】

200 6

6600

3 200

 

4 200

 

5 200

 

6 200

 

7 200

 

8 200

 

9 9

1260

10 3

 

9 3

 

 

13 9

 

5 3

15 9

100 9

3 6

2 6

1 6

3 9

1610

100 3

 

100 3

 

100 3

 

100 3

 

100 2

 

100 1

 

50 1

 

30 2

 

1 1

 

 

这道题虽然是一道比较水的题目

但是也然我认识到一些比较重要的东西

如背包能求出最优值,而一些贪心则会导致算法错误

比如这道题,若直接贪心,那么就会导致一些值大的运动员无法得到足够时间发挥,

但是用背包思想处理的话,就不会产生此类情况,因为用容量减,就不会出现一些选手得不到全部时间发挥

背包会自我调控到能替代的运动员后面替换之

所以以后遇到类似题目,一定学会转换思想,换成背包试试

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

typedef long long ll;

const int maxn=500000+10;

struct my{
       ll k,I;
};

my a[maxn];

bool cmp(const my &x,const my &y){
     return x.k>y.k;
}

int main(){
    ll n,m;
    ll ans=0;
    scanf("%lld%lld",&m,&n);
    for (int i=1;i<=n;i++){
        scanf("%lld%lld",&a[i].k,&a[i].I);
    }
    int p=0;
    sort(a+1,a+1+n,cmp);
    m*=6;
    for (int i=1;i<=n;i++){
        if(m-a[i].I>=0){
            m-=a[i].I;
            ans+=(a[i].k*a[i].I);
        }
        else if(m>0) {
            m=0;
            ans+=(m*a[i].k);break;
        }
    }
    printf("%lld",ans);
return 0;
}

 

posted @ 2018-08-13 20:56  lmjer  阅读(148)  评论(0编辑  收藏  举报