HDU 1074 Doing Homework(状态压缩DP)
题意:有n门课,每门课有截止时间和完成所需的时间,如果超过规定时间完成,每超过一天就会扣1分,问怎样安排做作业的顺序才能使得所扣的分最小
思路:二进制表示。
1 #include<iostream> 2 #include<string> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<cstdio> 6 #include<set> 7 #include<map> 8 #include<vector> 9 #include<cstring> 10 #include<stack> 11 #include<cmath> 12 #include<queue> 13 #include <bits/stdc++.h> 14 using namespace std; 15 #define INF 0x3f3f3f3f 16 #define ll long long 17 #define clc(a,b) memset(a,b,sizeof(a)) 18 const int MAXN=1<<16; 19 struct node 20 { 21 int cost; 22 int pre; 23 int reduced; 24 } dp[MAXN]; 25 bool visited[MAXN]; 26 struct course 27 { 28 int deadtime; 29 int cost; 30 char name[201]; 31 } course[16]; 32 void output(int status) 33 { 34 int curjob=dp[status].pre^status; 35 int curid=0; 36 curjob>>=1; 37 while(curjob) 38 { 39 curid++; 40 curjob>>=1; 41 } 42 if(dp[status].pre!=0) 43 { 44 output(dp[status].pre); 45 } 46 printf("%s\n",course[curid].name); 47 } 48 int main() 49 { 50 // freopen("in.txt","r",stdin); 51 int T,n; 52 int i,j; 53 scanf("%d",&T); 54 while(T--) 55 { 56 scanf("%d",&n); 57 int upper=1<<n; 58 int dayupper=0; 59 for(i=0; i<n; i++) 60 { 61 scanf("%s%d%d",&course[i].name,&course[i].deadtime,&course[i].cost); 62 dayupper+=course[i].cost; 63 } 64 memset(visited,false,sizeof(visited)); 65 dp[0].cost=0; 66 dp[0].pre=-1; 67 dp[0].reduced=0; 68 visited[0]=true; 69 int work; 70 int tupper=upper-1; 71 for(j=0; j<tupper; j++) 72 { 73 for(work=0; work<n; work++) 74 { 75 int cur=1<<work; 76 if((cur&j)==0) 77 { 78 int curtemp=cur|j; 79 int day=dp[j].cost+course[work].cost; 80 dp[curtemp].cost=day; 81 int reduce=day-course[work].deadtime; 82 if(reduce<0)reduce=0; 83 reduce+=dp[j].reduced; 84 if(visited[curtemp]) 85 { 86 if(reduce<dp[curtemp].reduced) 87 { 88 dp[curtemp].reduced=reduce; 89 dp[curtemp].pre=j; 90 } 91 } 92 else 93 { 94 visited[curtemp]=true; 95 dp[curtemp].reduced=reduce; 96 dp[curtemp].pre=j; 97 } 98 } 99 } 100 } 101 printf("%d\n",dp[tupper].reduced); 102 output(tupper); 103 } 104 }