完善程序-2解析

郊游活动)有 n 名同学参加学校组织的郊游活动,已知学校给这 n 名同学的郊游总经费为 A 元,与此同时第 i 位同学自己携带了 Mi​ 元。为了方便郊游,活动地点提供 B(≥n) 辆自行车供人租用,租用第 j 辆自行车的价格为 Cj​ 元,每位同学可以使用自己携带的钱或者学校的郊游经费,为了方便账务管理,每位同学只能为自己租用自行车,且不会借钱给他人,他们想知道最多有多少位同学能够租用到自行车。(第四、五空 2.52.5 分,其余 33 分)

本题采用二分法。对于区间 [l,r] ,我们取中间点 midmid 并判断租用到自行车的人数能否达到 mmid。判断的过程是利用贪心算法实现的。

原始数据:

序号1234567经费
同学携带的钱数3945266
自行车租用价格1071581335

算法:
第1个逻辑步骤:对同学和车两个序列排序(快速排序)
第2个逻辑步骤:查找能满足同学(二分法)
第3个逻辑步骤:用钱多的同学去租最便宜的自行车,经费是否够用(贪心算法)

序号1234567经费
同学携带的钱数2345696
自行车租用价格3578101315
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <iostream>
using namespace std;
#define MAXN 1000000
//n是同学数,B是自行车数量,M[]是自己带的钱,C[]是车的钱
int n,B,A,M[MAXN],C[MAXN],l,r,ans,mid;
//从钱多的同学去租便宜的自行车
bool check(int nn){ //check判断nn是指同学可以有自行车
    int count=0,i,j;
    i=n-nn+1; //反着数,因为是从钱多的同学配自行车
    j=1;
    while(i<=n){   
        if(M[i]<C[j]) //如果学生的钱不够
        count+=C[j]-M[i]; //count是补了多少钱,累加
        i++;
        j++;
    }
     return  count<=A; //保证钱够
}
void sort(int a[],int l,int r){ //快速排序
    int i=l,j=r,x=a[(l+r)/2],y;
    while(i<=j){
        while(a[i]<x)i++; 
        while(a[j]>x)j--;
        if(i<=j){
            y=a[i];
            a[i]=a[j];
            a[j]=y;
            i++;
            j--;
        }
    }
    if(i<r)sort(a,i,r);
    if(l<j)sort(a,l,j);
}
int main(){
    int i;
    cin>>n>>B>>A;
    for ( i = 1; i <= n; i++)cin>>M[i];//每位同学的钱
    for ( i = 1; i <=B; i++)cin>>C[i];//每辆自行车的钱
    sort(M,1,n); //对学生排序
    sort(C,1,B);//车辆排序
    l=0;
    r=n;
    while(l<=r){//二分查找
        mid=(l+r)/2;
        if(check(mid)){
            ans=mid;
            l=mid+1;
        }else
        r=mid-1;
    }
   
    
    cout<<ans<<endl;
    return 0;
}
Scroll to Top