HDU 1074 Doing Homework DP 状压DP
Posted FriskyPuppy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 1074 Doing Homework DP 状压DP相关的知识,希望对你有一定的参考价值。
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1074
题目描述: 给你所有课程的截止时间和工作时长, 一次只能做一种作业, 问最少罚时几天 N <= 15
解题思路: 由于N很小, 所以第一反应就是状压DP, 我们可以用一个15位二进制数来表示各个课程做完还是没做完, 然后从 S 从 1 到 1 << N 枚举 i 从 1 到 N 枚举, 如果S & (1<<i) 有效则说明i 属于情况 S, 这样我们从上一步S - 1 << i 转移过来就可以, 记录路径就是每当出现答案的更新就将此时的状态和当前处理的位数记住, 压入栈中, 最后再倒着打出来
代码:
#include <iostream> #include <cstdio> #include <string> #include <vector> #include <map> #include <cstring> #include <iterator> #include <cmath> #include <algorithm> #include <stack> #include <deque> #include <set> #include <iterator> #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 using namespace std; const int maxn = 20; int deadline[maxn]; int cost[maxn]; string name[maxn]; const int INF = 0x3fffffff; set<string> ans; struct node { int time, score, pre, now; }; node dp[1<<15]; set<string>::iterator it; int main() { int t; cin >> t; while( t-- ) { ans.clear(); memset(dp, 0, sizeof(dp)); int n; cin >> n; for( int i = 0; i < n; i++ ) { cin >> name[i] >> deadline[i] >> cost[i]; } int end = 1 << (n); // cout << end << endl; for( int s = 1; s < end; s++ ) { dp[s].score = INF; for( int i = n-1; i >= 0; i-- ) { int temp = 1 << i; if( temp & s ) { int past = s- temp; int st = dp[past].time + cost[i] - deadline[i]; if( st < 0 ) st = 0; if( st + dp[past].score < dp[s].score ) { dp[s].score = st + dp[past].score; dp[s].pre = past; dp[s].now = i; dp[s].time = dp[past].time + cost[i]; } } } } stack<int> S; int tem = end-1; cout << dp[tem].score << endl; while(tem) { S.push(dp[tem].now); tem = dp[tem].pre; } while(!S.empty()) { cout << name[S.top()] << endl; S.pop(); } } return 0; }
思考: 自己一开始只知道是状压DP, 具体该怎么做还是不知道, 要接触各种DP
以上是关于HDU 1074 Doing Homework DP 状压DP的主要内容,如果未能解决你的问题,请参考以下文章
[2016-03-28][HDU][1074][Doing Homework]