HDU1074 Doing Homework【状态压缩入门】

Doing Homework

题意: 要完成n门课的作业,每门课的作业分别具有一个截至时间和一个完成需要的时间。此外作业超过截止时间提交需要扣相应的分数。求最小扣分,并按最小字典序输出作业完成顺序。

题解: n ≤ 15,一个美丽的范围,对于这样的数据,都可以考虑通过状态压缩来完成。

#include<bits/stdc++.h>
using namespace std;
inline int read() {
   int s = 0, w = 1;
   char ch = getchar();
   while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
   while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
   return s * w;
}

const int inf = 0x3f3f3f3f;
const int maxn = (1 << 15) + 10;
int dp[maxn], t[maxn];	//dp[i]记录到达状态i扣的最少分,t时相应的花去多少天了
int pre[maxn]; 			//特别的是,只有dp需要进行初始化
int ddl[20], fin[20];	//截止时间、完成时间
char s[20][100];

void print(int x) {
	if(x == 0)	return;
	print(x - (1 << pre[x]));
	printf("%s\n", s[pre[x]]);
}

void run() {
	int n = read();
	for(int i = 0; i < n; i++) scanf("%s%d%d", s[i], &ddl[i], &fin[i]);
	int tot = 1 << n;	//状态
	for(int i = 1; i < tot; i++) {
		dp[i] = inf;	初始化到达状态i的扣分
		for(int j = n - 1; j >= 0; j--) {	//为保证字典序的最小,从后往前遍历
			int tem = 1 << j;			//单完成作业j的状态
			if(!(i & tem))	continue;	//状态i中并没有完成作业j
			int score = t[i - tem] + fin[j] - ddl[j];
			if(score < 0) score = 0;	//i-tem表示没有完成j的那个状态
			if(dp[i] > dp[i - tem] + score) {
				dp[i] = dp[i - tem] + score;
				t[i] = t[i - tem] + fin[j];
				pre[i] = j;		//i对应的是完成某些作业时的状态,而j对应作业的编号
			}	//状态都是独一无二的,所以某个状态的pre不用特意初始化
		} 
	}
	printf("%d\n", dp[tot - 1]);
	print(tot - 1);
}

int main() {
	int _T = read();
	while(_T--)	run();
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值