【算法系列学习】状压dp [kuangbin带你飞]专题十二 基础DP1 D - Doing Homework
https://vjudge.net/contest/68966#problem/D
http://blog.csdn.net/u010489389/article/details/19218795
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<algorithm> 6 #include<cmath> 7 #include<queue> 8 #define INF 0x3f3f3f3f 9 using namespace std; 10 const int maxn=105; 11 int n; 12 struct hmwk 13 { 14 char ch[maxn]; 15 int d; 16 int c; 17 }p[16]; 18 19 struct DP 20 { 21 int time; 22 int reduced; 23 int fa; 24 }dp[(1<<15)]; 25 26 char s[16][101]; 27 28 void Init() 29 { 30 for(int i=0;i<(1<<15);i++) 31 { 32 dp[i].fa=-1; 33 dp[i].time=0; 34 dp[i].reduced=INF; 35 } 36 dp[0].reduced=0; 37 38 } 39 //按字典序增序输出 40 bool cmp(const hmwk&x,const hmwk& y) 41 { 42 return strcmp(x.ch,y.ch)<=0; 43 } 44 //递归输出,x为当前,fa为前一个 45 void Print(int x,int fa) 46 { 47 int flag; 48 if(x==0) 49 { 50 for(int i=0;i<n;i++) 51 { 52 if(fa&(1<<i)) 53 { 54 flag=i; 55 break; 56 } 57 } 58 printf("%s\n",p[flag].ch); 59 return; 60 } 61 Print(dp[x].fa,x); 62 for(int i=0;i<n;i++) 63 { 64 if((x&(1<<i))!=(fa&(1<<i))) 65 { 66 flag=i; 67 break; 68 } 69 } 70 if(x==0) 71 { 72 printf("%s\n",p[flag].ch); 73 } 74 else 75 { 76 printf("%s\n",p[flag].ch); 77 } 78 } 79 80 int main() 81 { 82 int T; 83 scanf("%d",&T); 84 while(T--) 85 { 86 87 scanf("%d",&n); 88 for(int i=0;i<n;i++) 89 { 90 scanf("%s%d%d",p[i].ch,&p[i].d,&p[i].c); 91 } 92 sort(p,p+n,cmp); 93 Init(); 94 //每个i代表一个状态,i的每一位代表一个科目 95 for(int i=0;i<(1<<n);i++) 96 { 97 for(int k=0;k<n;k++) 98 { 99 //如果是1跳过 100 if(i&(1<<k)) 101 { 102 continue; 103 } 104 //now为转移后的状态 105 int now=i+(1<<k); 106 dp[now].time=dp[i].time+p[k].c; 107 //dp[now].time-p[k].d<0说明没有延期,就是0 108 if(dp[i].reduced+max(0,dp[now].time-p[k].d)<dp[now].reduced) 109 { 110 dp[now].reduced=dp[i].reduced+max(0,dp[now].time-p[k].d); 111 dp[now].fa=i; 112 } 113 } 114 } 115 //最终结果就是111111(n个1),对应的数就是(1<<n)-1 116 printf("%d\n",dp[(1<<n)-1].reduced); 117 Print(dp[(1<<n)-1].fa,(1<<n)-1); 118 } 119 return 0; 120 }