题意:有n个任务,每个任务都有完成时间和完成期限,惩罚值就是超出期限的时间,问所有任务完成的最大和第二大惩罚值之和最小是多少。

题解:先排序,期限越小的排前面,否则就时间短的先完成,但只这样不一定是最优解,可以牺牲某个任务使最终解更优,所以将牺牲掉任务的位置放到之前得到的第二大惩罚值的前面,这样可以使最大惩罚值减小,遍历之前的所有任务,更新最小值。

#include <stdio.h>
#include <algorithm>
using namespace std;
const int N = 505;
struct Work {
	int s, d;
}w[N];
int n, pos;

int cmp(Work a, Work b) {
	if (a.d != b.d)
		return a.d < b.d;
	return a.s < b.s;
}

int solve(int x) {
	int max1 = 0, max2 = 0, t = 0;
	for (int i = 0; i <= pos; i++) {
		if (i == x)
			continue;
		t += w[i].s;
		int k = max(0, t - w[i].d);
		max2 = max(max2, k);
		if (max2 > max1)
			swap(max1, max2);
	}
	t += w[x].s;
	int k = max(0, t - w[x].d);
	max2 = max(max2, k);
	return max1 + max2;
}

int main() {
	int t;
	scanf("%d", &t);
	while (t--) {
		scanf("%d", &n);
		for (int i = 0; i < n; i++)
			scanf("%d%d", &w[i].s, &w[i].d);
		sort(w, w + n, cmp);
		int max1 = 0, max2 = 0, t = 0;
		for (int i = 0; i < n; i++) {
			t += w[i].s;
			if (t - w[i].d >= max2) {
				pos = i;
				max2 = t - w[i].d;
			}
			if (max2 > max1)
				swap(max1, max2);
		}
		int res = max1 + max2;
		for (int i = 0; i < pos; i++)
			res = min(res, solve(i));
		printf("%d\n", res);
	}
	return 0;
}