HDU1074.Doing Homework
题意
给n个作业,每个作业都有一个截止日期,和一个做完所需的时间,超过截止时间写每天扣 1 分, 问最少扣几分可以完成全部作业并输入方案(完成的顺序,相同输出字典序最小)(n<=15)
分析
状压dp入门,从数据范围就可以看出状压的思路?n最大15, 考虑二进制0/1表示每门作业的完成情况,则需要2^15,dp[i] : 表示状态i的最有解
再把状态i中所有作业完成的顺序枚举出来求出最优即可,每次记录一下转移的方向即可
#include<bits/stdc++.h> using namespace std; const int maxn = (1<<15) + 10; int dp[maxn]; int path[maxn]; int decline[20]; int cost[20]; int tme[maxn]; int n; char s[20][105]; void print(int num) { if(!num) return; print(num-(1<<path[num])); printf("%s ",s[path[num]]); } int main() { int t; scanf("%d", &t); while(t--) { scanf("%d", &n); for(int i = 0; i < n; i++) { scanf("%s%d%d", s[i], &decline[i], &cost[i]); } dp[0] = 0; memset(path,0,sizeof(path)); for(int i = 1; i < (1<<n); i++) { dp[i]=1e9; for(int j = n-1; j >= 0; j--) { int temp = (1<<j); if(!(temp & (i))) continue; int ans = tme[i^temp]+cost[j]-decline[j]; if(ans<0) ans = 0; if(dp[i] > dp[i^temp]+ans) { dp[i] = dp[i^temp]+ans; tme[i]=tme[i^temp]+cost[j]; path[i]=j; } } } printf("%d ", dp[(1<<n)-1]); print((1<<n)-1); } }