百练 4149: 课程大作业

本文介绍了一种解决课程选择问题的动态规划算法,考虑到课程的时间冲突和完成所有课程所需的最小时间,同时确保选择的课程序列在字典序上是最小的。通过比较不同的课程序列,算法能够在满足时间条件的前提下找到最优解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值