题目抽象:给出n个task的name,deadline,need。 每个任务的罚时penalty=finish-deadline; task不可以同时做。问按怎样的顺序做使得penalty最小。同时输出顺序。如果有多个满足条件的顺序,按字典序输出。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <string> 7 #include <vector> 8 #include <stack> 9 #include <queue> 10 #include <set> 11 #include <map> 12 #include <list> 13 #include <iomanip> 14 #include <cstdlib> 15 #include <sstream> 16 using namespace std; 17 typedef long long LL; 18 const int INF=0x5fffffff; 19 const double EXP=1e-6; 20 const int MS=16; 21 22 struct task 23 { 24 char name[105]; 25 int deadline,need; 26 }tasks[MS]; 27 28 struct node 29 { 30 int time,penalty; // 到达这个状态的时间,和罚时 31 int cur,pre; // 状态s的物理变化过程 32 }nodes[1<<MS]; 33 34 int n,m; 35 36 void solve() 37 { 38 for(int i=1;i<=m;i++) // note i==1 39 nodes[i].penalty=INF; 40 nodes[0].time=0; 41 for(int i=0;i<=m;i++) 42 { 43 for(int j=0;j<n;j++) 44 if(!((i>>j)&1)) 45 { 46 int next=i|(1<<j); 47 int finish=nodes[i].time+tasks[j].need; 48 int penalty=max(0,finish-tasks[j].deadline); 49 penalty+=nodes[i].penalty; 50 if(penalty<nodes[next].penalty) 51 { 52 nodes[next].time=finish; 53 nodes[next].penalty=penalty; 54 nodes[next].cur=j; 55 nodes[next].pre=i; 56 } 57 } 58 } 59 } 60 61 void output(int x) 62 { 63 if(x==0) 64 return ; 65 output(nodes[x].pre); 66 printf("%s ",tasks[nodes[x].cur].name); 67 } 68 69 int main() 70 { 71 int T; 72 scanf("%d",&T); 73 while(T--) 74 { 75 scanf("%d",&n); 76 for(int i=0;i<n;i++) 77 scanf("%s%d%d",tasks[i].name,&tasks[i].deadline,&tasks[i].need); 78 m=(1<<n)-1; 79 solve(); 80 printf("%d ",nodes[m].penalty); 81 output(m); 82 } 83 return 0; 84 }