NOIP 2016 普及组初赛试题_完善程序 4.2 郊游活动
已知学校给这 n 名同学 的郊游总经费为 A 元,
与此同时第 i 位同学自己携带了 Mi 元。
为了方便郊游,活动地点提供 B(≥n)辆自行车供人租用,
每位同学可以使用自己携带的钱或者学校的郊游经费,
为了方便账务管理,每位同学只能为自己租用自行车,
且不会借钱给他人,他们想知道最多有多少位同学能够租用到自行车。
(第四、五空 2.5 分,其余 3 分)
本题采用二分法。
对于区间[l, r],
我们取中间点 mid 并判断租用到自行车的人数能否达到 mid。
判断的过程是利用贪心算法实现的。
#include <iostream>
using namespace std;
#define MAXN 1000000
int n, B, A, M[MAXN], C[MAXN], l, r, ans, mid;
//我们取中间点 mid 并判断租用到自行车的人数能否达到 mid。
//判断nn人能不能都租到车子
bool check(int nn)
{
int count = 0, i, j;
i = ①;//i=n-nn+1; [0,mid]
j = 1;
while (i <= n)
{
//与此同时第 i 位同学自己携带了 Mi 元。
//count就学校出的钱,如果自己带的钱够租,尽量不要让学校出钱
//如果自己带的钱不够,让学校负担 C[j] - M[i]的钱
if(②)// M[i]<=C[j]
count += C[j] - M[i];
//还需要多少钱才能租到mid辆的自行车
i++;
j++;
}
return ③;//cout<=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( void )
{
int i;
//已知学校给这 n名同学的郊游总经费为 A 元,
//为了方便郊游,活动地点提供 B(≥n)辆自行车供人租用,
cin >> n >> B >> A;
//与此同时第 i 位同学自己携带了 Mi 元。
for (i = 1; i <= n; i++)
cin >> M[i];
//租用第 i 辆自行车的价格为 C[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)
//mid个人可以租到自行车
{
ans = mid;
l = mid + 1;
}else
r = ⑤;//mid-1
}
//最多有多少位同学能够租用到自行车。
cout << ans << endl;
return 0;
}
1.正确答案: n-nn+1
2.正确答案: M[i]<C[j] / M[i]<=C[j]
3.正确答案: count<=A
4.正确答案: check(mid)
5.正确答案: mid-1