题意:
给你N个课程, 每个课程有结束的时间 , 和完成这门课程需要的时间
超过课程结束ed时间,每一天就要花费 1点绩点;
然后要求你安排如何做课程使得花费的绩点最少
(看了博客后才发现状态压缩很⑥)
用二进制表示状态 + 前驱标记
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<stack> using namespace std; typedef long long ll; struct Node { int now, pre;//当前标号 和之前的标号 int time;//当前时间 int Get;//消耗 }; struct Class { int last; int cost; char name[30]; }; Node Dp[1<<20]; Class Num[20]; int main() { int t; scanf("%d",&t); while(t--) { int n; scanf("%d",&n); for(int i = 0; i < n; ++i) { scanf("%s %d %d",&Num[i].name,&Num[i].last,&Num[i].cost); } memset(Dp,0,sizeof(Dp)); int nn = 1<<n; for(int s = 1; s < nn; ++s) { Dp[s].Get = (1<<30); for(int j = n-1; j >= 0; --j) { if(s & (1 << j)) { int Pre = s - (1 << j); ///之前的状态 int New = Dp[Pre].time + Num[j].cost - Num[j].last; if(New < 0) New = 0; ///如果还没到结束时间,新的就为0 if(Dp[Pre].Get + New < Dp[s].Get) { Dp[s].Get = Dp[Pre].Get + New; Dp[s].time = Dp[Pre].time + Num[j].cost; Dp[s].pre = Pre; Dp[s].now = j; } } } } nn --; printf("%d\n",Dp[nn].Get); stack<Class> SS; while(nn) { //printf("%s\n",Num[Dp[nn].now].name); SS.push(Num[Dp[nn].now]); nn = Dp[nn].pre; } while(!SS.empty()) printf("%s\n",SS.top().name), SS.pop(); } }