百練 4149: 課程大作業

dp,麻煩的是需要字典序最小,每次更新dp需要進行判斷。

#define _CRT_SECURE_NO_WARNINGS
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;

const int N = 15 + 5;

struct Course {
	char s[50 + 5];
	int ed, time;
	bool operator<(const Course& c)const {
		return strcmp(s, c.s) < 0;
	}
}cor[N];

int dp[1 << 20], pre[1 << 20];

void print(int x, vector<int>& v) {
	if (x == 0) return;
	print((1 << pre[x]) ^ x, v);
	v.push_back(pre[x]);
}

int big(vector<int> a, vector<int> b) {
	for (int i = 0; i < a.size(); i++){
		if (a[i] > b[i]) return 1;
		if (a[i] < b[i]) return 0;
	}
	return 0;
}

int main() {
	int t; scanf("%d", &t);
	while (t--) {
		int n; scanf("%d", &n);
		for (int i = 0; i < n; i++)
			scanf("%s%d%d", cor[i].s, &cor[i].ed, &cor[i].time);
		sort(cor, cor + n);
		for (int i = 0; i < (1 << n); i++)
			dp[i] = 1e7;
		dp[0] = 0;
		for (int i = 0; i < (1 << n); i++) {
			int pret = 0;
			for (int j = 0; j < n; j++)
				if ((i >> j) & 1)
					pret += cor[j].time;
			for (int j = 0; j < n; j++)
				if (!((i >> j) & 1))
				{
					int now = dp[i] + (cor[j].ed < pret + cor[j].time ? cor[j].time + pret - cor[j].ed : 0);
					if (now < dp[(1 << j) + i]) {
						dp[(1 << j) + i] = now;
						pre[(1 << j) + i] = j;
					}
					else if (now == dp[(1 << j) + i]) {
						vector<int> v1, v2;
						print((1 << j) + i,v1);
						print(i, v2);
						v2.push_back(j);
						if(big(v1,v2)) pre[(1 << j) + i] = j;
					}
				}
		}
		printf("%d\n", dp[(1 << n) - 1]);
		vector<int> path;
		print((1 << n) - 1, path);
		for (int i = 0; i < path.size(); i++)
			printf("%s\n", cor[path[i]].s);
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章