Doing Homework HDU - 1074(状压DP)

Doing Homework

题目链接:HDU - 1074
题意:有n科作业需要做, 给出每科作业的名字, 上交时间(最晚完成期限), 完成作业需要的时间;当作业完成时已超过最晚期限, 则每超一天扣一分;让你合理安排时间, 使得扣分最少, 然后输出路径, 如果有多个答案输出字典序最小的;
n的范围是1~15, 一共n!种情况, 扫一遍所有情况明显不靠谱, 想到了状压DP, dp[i]表示状态扣的分, path[i]表示i状态是作path[i]得到的(这就是路径, 最后递归输出),time[i]表示状态已经用了time[i]时间;
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=35000;
const int INF=0x3f3f3f3f;
int N;
char s[20][150];
int d[20], t[20];
int dp[maxn], path[maxn], time[maxn];
void print(int x){
	if(x==0) return; 
	print(x-(1<<(path[x]-1)));
	printf("%s\n", s[path[x]]);
}
int main(){
	int T;
	scanf("%d", &T);
	while(T--){
		scanf("%d", &N);
		for(int i=1; i<=N; i++){
			scanf("%s%d%d", s[i], &d[i], &t[i]);
		}
		memset(time, 0, sizeof(time));
		for(int i=1; i<(1<<N); i++){
			dp[i]=INF;
			for(int j=N; j>0; j--){//题目要求字典序最小;
				if((i&(1<<(j-1)))==0) continue;
				int score=time[i-(1<<(j-1))]+t[j]-d[j];
				if(score<=0) score=0;
				if(dp[i]>dp[i-(1<<(j-1))]+score){//因为for循环是N~1,所以这里没有等号,保证字典序最小,若循环变为1~N,这里加上等号;
					dp[i]=dp[i-(1<<(j-1))]+score;
					time[i]=time[i-(1<<(j-1))]+t[j];
					path[i]=j;
				}
			}
		}
		printf("%d\n", dp[(1<<N)-1]);
		print((1<<N)-1);
	}
	return 0;
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值