Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 15868 Accepted Submission(s): 7718
node
題意:ios
有T測試用例,每一個用例有個N門做業,每門做業有截止時間和完成所需的時間,默認時間爲0,在截止時間事後每拖一天就會扣一分,求作做業的順序讓扣的分最少,若是有多個答案則輸出字典序最小的答案(注意!),且輸入的課程名稱按字母順序遞增。app
思路:測試
由於題目只有十五門課程,能夠暴力狀壓DP,枚舉1~1<<n的全部狀態。具體見下代碼。(不要在乎頭文件)this
#define _CRT_SECURE_NO_DepRECATE #define _CRT_SECURE_NO_WARNINGS #include <cstdio> #include <iostream> #include <cmath> #include <iomanip> #include <string> #include <algorithm> #include <bitset> #include <cstdlib> #include <cctype> #include <iterator> #include <vector> #include <cstring> #include <cassert> #include <map> #include <queue> #include <set> #include <stack> #define ll long long #define INF 0x3f3f3f3f #define ld long double const ld pi = acos(-1.0L), eps = 1e-8; int qx[4] = { 0,0,1,-1 }, qy[4] = { 1,-1,0,0 }, qxx[2] = { 1,-1 }, qyy[2] = { 1,-1 }; using namespace std; struct node { string name; int need, end; }book[20]; struct fate { int last, now, score, day; }dp[1<<15]; int main() { ios::sync_with_stdio(false); cin.tie(0); int T; cin >> T; while (T--) { int n; cin >> n; for (int i = 0; i < n; i++) { cin >> book[i].name >> book[i].end >> book[i].need; } memset(dp, 0, sizeof(dp)); for (int i = 1; i < 1 << n; i++)//枚舉作做業的每種狀況 { dp[i].score = INF; for (int f = n - 1; f >= 0; f--) { int s = 1 << f;//讓1表明選擇作哪一門課 if (s & i)//判斷該狀況是否有作這一門課 { int last = i - s;//last爲沒作s這門課的時候 int score = max(dp[last].day + book[f].need - book[f].end, 0);//計算作s這門課的時候的分數,分數不能小於0 if (score + dp[last].score < dp[i].score)//若是作s這門課得分更少則作這麼課 { dp[i].score = score + dp[last].score; dp[i].day = dp[last].day + book[f].need; dp[i].last = last;//記錄得分最少的上一種狀況,記錄路徑 dp[i].now = f;//記錄此時選作哪一門課,注意是倒着選的 } } } } cout << dp[(1 << n) - 1].score << endl;//(1 << n) - 1的狀況即爲作所有做業的時候,DP的思想。 int out = (1 << n) - 1; stack<string>output; while (out) { output.push(book[dp[out].now].name);//由於是倒着記錄的因此應用stack記錄而後輸出 out = dp[out].last; } while (!output.empty()) { cout << output.top() << endl; output.pop(); } } return 0; }