hdu6667 19年杭电多校赛第八场第11题

								Roundgod and Milk Tea

Time Limit: 6000/6000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 408 Accepted Submission(s): 198

Problem Description
Roundgod is a famous milk tea lover at Nanjing University second to none. This year, he plans to conduct a milk tea festival. There will be n classes participating in this festival, where the ith class has ai students and will make bi cups of milk tea.

Roundgod wants more students to savor milk tea, so he stipulates that every student can taste at most one cup of milk tea. Moreover, a student can’t drink a cup of milk tea made by his class. The problem is, what is the maximum number of students who can drink milk tea?

Input
The first line of input consists of a single integer T (1≤T≤25), denoting the number of test cases.

Each test case starts with a line of a single integer n (1≤n≤106), the number of classes. For the next n lines, each containing two integers a,b (0≤a,b≤109), denoting the number of students of the class and the number of cups of milk tea made by this class, respectively.

It is guaranteed that the sum of n over all test cases does not exceed 6×106.

Output
For each test case, print the answer as a single integer in one line.

Sample Input
1
2
3 4
2 1

Sample Output
3
题意: n个班级,每个班级有ai个人,每个班级制作bi杯奶茶,同一个班的只能和其他班制作的奶茶,问最多有多少人能喝到奶茶。
思路: 利用贪心思想,先对数组进行排序,奶茶数量多的排在前面,相同时,人数多的排在前面。用一个pre记录当前班级前面一共制作的奶茶数量,用sum记录当前班级后一共制作的奶茶数量,每次从当前班级的后面取找满足当前班级人数的奶茶数量,即先从后面开始取,后面全部取完再考虑前面班级剩余的奶茶数,详情看代码和注释。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 5;
struct node {
	ll a, b;
}g[N];

bool cmp(node p, node q) {
	if (p.b == q.b) return p.a > q.a; //奶茶数相同时,班级人数多的在前面 
	else return p.b > q.b; // 奶茶数大的排在前面 
}

int main() {
	int t, n;
	scanf("%d", &t);
	while (t--) {
		scanf("%d", &n);
		ll sum = 0, pre = 0, ans = 0;
		for (int i = 0; i < n; i++) {
			scanf("%lld%lld", &g[i].a, &g[i].b);
			sum += g[i].b; // 记录总的奶茶数量 
		}
		sort(g, g + n, cmp); 
		int flag = 0, k = 0;
		for (int i = 0; i < n; i++) {
			if (flag) { // 如果当前后面的奶茶都分配完毕,找当前前面的奶茶数 
				if (pre == 0) break; // 为0是直接结束 
				if (pre >= g[i].a) { // 当前奶茶数大于班级人数 
					pre -= g[i].a; // 奶茶数减去人数 
					ans += g[i].a; // 答案加上人数 
				} else {
					ans += pre;	// 否则直接加上奶茶数				
					pre = 0; // 赋值为0 
				}
			} else {
				if (sum - g[i].b >= g[i].a) { // 当前后面剩余的奶茶数大于当前班级人数 
					ll temp = g[i].a; // 取出当前班级人数 
					ans += temp; // 答案加上当前人数 
					sum -= g[i].b; // 后面剩余奶茶数减去当前班级制作的数量 
					g[i].a = 0; // 将该班级人数置0 
					k = max(k, i + 1); // 取出上次选择的第k个班级的位置 
					for (; k < n; k++) { // 从后往前找,直至找到能满足当前班级人数的奶茶数量 
						if (g[k].b == 0) continue;
						else if (g[k].b <= temp) { // 当前班级的奶茶数小于班级人数 
							temp -= g[k].b; // 人数减去奶茶数,即剩余还未分配奶茶人数 
							sum -= g[k].b; // 剩余奶茶减去当前班级制作的数量 
							g[k].b = 0; // 将该班级制作的奶茶数置为0 
						} else {
							g[k].b -= temp; // 否则,求出该班级还剩余的奶茶数 
							sum -= temp; // 更新剩余的总奶茶数 
							break; // 当前班级分配完毕,结束枚举 
						}
					}
					pre += g[i].b; // 记录这个班级制作的奶茶数,作为其他班级还能选择的数量 
				} else {
					ans += sum - g[i].b; // 加上能分配的人数 
					g[i].a -= sum - g[i].b; // 算出该班级剩余未分配到奶茶的人数 
					sum = 0; // 后面班级的奶茶分配完毕 
					flag = 1; // 标记 
					k = max(k, i + 1); // 取出之前分配记录的位置,后面的奶茶数全部置为0 
					for (; k < n; k++) {
						g[k].b = 0;
					}
					if (pre >= g[i].a) { // 如果之前的班级剩余的奶茶数大于该班级人数 
						ans += g[i].a; // 答案加上当前班级人数 
						pre -= g[i].a;	// 更新剩余奶茶数					
					} else {
						ans += pre; // 加上剩余奶茶数 
						pre = 0; // 全部分配,置为0 
					}
					pre += g[i].b; // 加上当前班级制作的奶茶数 
				}
			}
		}
		printf("%lld\n", ans);
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章