hdu 1074 Doing Homework(状压dp)
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1074
题意:有n门课,每门课有截止时间和完成所需的时间,如果超过规定时间完成,每超过一天就会扣1分,问怎样安排做作业的顺序才能使得所扣的分最小
由于课目数最多只有15个,所以可以遍历所有状态1~1<<(n - 1)然后再找最优解至于字典序可以不用考虑题目已经帮你处理好了只要按顺序来就能满足
字典序小的先
#include <iostream>
#include <cstring>
#include <string>
#include <stack>
using namespace std;
const int M = 1 << 16;
struct TnT {
string s;
int cost , deadline , pre , reduce , now;
}a[20] , dp[M];
bool vis[M];
int main() {
int t;
cin >> t;
while(t--) {
int n;
memset(vis , false , sizeof(vis));
dp[0].cost = 0;
dp[0].pre = -1;
dp[0].reduce = 0;
cin >> n;
for(int i = 0 ; i < n ; i++) {
cin >> a[i].s >> a[i].deadline >> a[i].cost;
}
int End = 1 << n;
End--;
vis[0] = true;
for(int i = 0 ; i < End ; i++) {
for(int j = 0 ; j < n ; j++) {
int temp = 1 << j;
if((i & temp) == 0) {
int gg = (i | temp);
dp[gg].cost = dp[i].cost + a[j].cost;
int reduce = dp[gg].cost - a[j].deadline;
reduce = max(0 , reduce);
reduce += dp[i].reduce;
if(vis[gg]) {
if(reduce < dp[gg].reduce) {
dp[gg].reduce = reduce;
dp[gg].now = j;
dp[gg].pre = i;
}
}
else {
vis[gg] = true;
dp[gg].pre = i;
dp[gg].now = j;
dp[gg].reduce = reduce;
}
}
}
}
cout << dp[End].reduce << endl;
int gl = End;
stack<int>ss;
while(dp[gl].pre != -1) {
ss.push(dp[gl].now);
gl = dp[gl].pre;
}
while(!ss.empty()) {
cout << a[ss.top()].s << endl;
ss.pop();
}
}
return 0;
}

浙公网安备 33010602011771号