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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章