C++题解打卡Day 2——食堂打菜

【题目描述】

        一实食堂有 n 个菜,第 i 个菜的价格是 C[i] 元钱,现有 q 个同学,第 i 个同学的饭卡有X[i]元钱。

        问第 i 个同学最多能打多少个菜?

【输入】

        第 1 行 1 个整数 n

        第 2 行 n 个整数 C[1]...C[n]

        第 3 行 1 个整数 q

        第 4 行 q 个整数 X[1]...X[q]

【输出】

        输出 q 行, 第 i 行表示第 i 个同学最多能打多少菜。

【输入输出样例】

        Input

5
300 100 400 100 500
3
500 250 40

        Output

3
2
0

【数据范围】

        1\leq n,q \leq 10^{5}

        1 \leq C_i \leq 10^{4}

        1 \leq X_j \leq 10^{9}

【题解】

        讲两种做法。

     【做法一、传统贪心】

        首先,对 C 数组进行排序

        然后,遍历每一个学生所拥有的钱,并在内遍历 C 数组。设立一个计数变量 ans,用来记录已经打的菜品数量,并设立一个变量 cnt,用来记录已打菜品所花的钱,一旦 cnt \geq X_i,就输出 ans

        代码实现如下:

#include<bits/stdc++.h>
using namespace std;
int n,q;
int c[100100],x[100100],cnt,ans;
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0); 
	cin >> n;
	for(int i = 1;i <= n;i++){
		cin >> c[i]; 
	}	
	cin >> q;
	for(int i = 1;i <= q;i++){
		cin >> x[i];
	}
	sort(c + 1,c + 1 + n);
	for(int i = 1;i <= q;i++){
		cnt = 0;
		ans = 0;
		bool flag = true;
		for(int j = 1;j <= n;j++){
			cnt += c[j];
			if(cnt > x[i]){
				cout << ans << "\n";
				flag = false;
				break;
			}
			else if(cnt == x[i]){
				ans++;
				cout << ans << "\n";
				flag = false;
				break;
			}
			ans++;
		}
		if(flag == true){
			cout << n << "\n"; // 如果他可以把所有菜都打一遍,就直接输出n
		}
	}
	return 0;
}

        该做法的时间复杂度是O(n^{2}),很明显超时了。

     【做法二、前缀和+二分查找】

        先对 C 数组排序,然后建立一个 arr 数组,用于存放 C_1 + C_2 +... + C_i,然后用二分查找函数 upper_bound 找出,最后输出即可,时间复杂度O(nlogn),代码实现如下

#include<bits/stdc++.h>
using namespace std;
int n,q;
int c[100100],x[100100],arr[100100];
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0); 
	cin >> n;
	for(int i = 1;i <= n;i++){
		cin >> c[i]; 
	}
	
	cin >> q;
	for(int i = 1;i <= q;i++){
		cin >> x[i];
	}
	sort(c + 1,c + 1 + n);
	for(int i = 1;i <= n;i++){
		arr[i] = arr[i - 1] + c[i];
	}
	for(int i = 1;i <= q;i++){
		int y = upper_bound(arr + 1,arr + 1 + n,x[i]) - arr;
		if(y == n){
			if(arr[y] > x[i]){
				cout << y - 1 << "\n";
			}
			else{
				cout << y << "\n";
			}
		}
		else{
			cout << y - 1 << "\n";
		}
	}
	return 0;
}

完结撒花!!!

制作不易,点个赞吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值