【状压DP】——hud1074—最小扣分——记录路径
Doing Homework
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 7896 Accepted Submission(s): 3596
Problem Description
Ignatius has just come back school from the 30th ACM/ICPC. Now he has a lot of homework to do. Every teacher gives him a deadline of handing in the homework. If Ignatius hands in the homework after the deadline, the teacher will reduce his score of the final test, 1 day for 1 point. And as you know, doing homework always takes a long time. So Ignatius wants you to help him to arrange the order of doing homework to minimize the reduced score.
Input
The input contains several test cases. The first line of the input is a single integer T which is the number of test cases. T test cases follow.
Each test case start with a positive integer N(1<=N<=15) which indicate the number of homework. Then N lines follow. Each line contains a string S(the subject's name, each string will at most has 100 characters) and two integers D(the deadline of the subject), C(how many days will it take Ignatius to finish this subject's homework).
Note: All the subject names are given in the alphabet increasing order. So you may process the problem much easier.
Each test case start with a positive integer N(1<=N<=15) which indicate the number of homework. Then N lines follow. Each line contains a string S(the subject's name, each string will at most has 100 characters) and two integers D(the deadline of the subject), C(how many days will it take Ignatius to finish this subject's homework).
Note: All the subject names are given in the alphabet increasing order. So you may process the problem much easier.
Output
For each test case, you should output the smallest total reduced score, then give out the order of the subjects, one subject in a line. If there are more than one orders, you should output the alphabet smallest one.
Sample Input
2
3
Computer 3 3
English 20 1
Math 3 2
3
Computer 3 3
English 6 3
Math 6 3
Sample Output
2
Computer
Math
English
3
Computer
English
Math
Hint
In the second test case, both Computer->English->Math and Computer->Math->English leads to reduce 3 points, but the
word "English" appears earlier than the word "Math", so we choose the first order. That is so-called alphabet order.题意:
给出每一门作业的名字,截止日期,需要的时间,
超出截止时间一天扣一分,求最小扣分,并输出作业顺序
思路:
做作业肯定是不休息,一口气做完是最优选择
那么我们就让所有时间点被任务占满
而罚时在于时间,
如果每个状态排满任务,那么达到每个状态的时间也就易求了。
注意这句:
Note: All the subject names are given in the alphabet increasing order. So you may process the problem much easier.
输入的时候已经是字典序了,
所以让后面的课程,在最优选择下仍排在最后即可
代码如下:
#include<iostream> #include<string.h> using namespace std; const int maxn=(1<<15)+10; string cla[20];//课程名称 int dp[maxn];//dp[s]表示 s 状态下最小罚分 int time[maxn];//time[s]表示 s 状态下所需时间 int fa[maxn];//该状态由那个任务转移而来 int del[20];//截止日期 int ned[20];//需要时间 void output(int s) { if(s!=0) { output(s-(1<<fa[s]));//差值代表状态 cout<<cla[fa[s]]<<endl; } } int main() { int t; cin>>t; while(t--) { memset(time,0,sizeof(time)); int n; cin>>n; for(int i=0;i<n;i++) cin>>cla[i]>>del[i]>>ned[i]; for(int s=1;s<(1<<n);s++) { dp[s]=0x7fffffff;//初始化:求最小设极大 //因为数位是从右往左,所以高位是靠前的元素,低位是靠后的元素 // j 从后往前的意思就是,在当前选择最优的情况下后面的元素(字典序大的)越排在后面越好 for(int j=n-1;j>=0;j--) { int now=1<<j;//当前选择的任务 if(s&now)//该状态中包括当前任务 { int fin=time[s-now]+ned[j]-del[j];//计算罚时 if(fin<0)fin=0;//罚时不能为负 if(dp[s-now]+fin<dp[s]) { dp[s]=dp[s-now]+fin; time[s]=time[s-now]+ned[j];//不同选择,所需时间也不同 fa[s]=j;//记录当前状态的选择 } } } } cout<<dp[(1<<n)-1]<<endl; output((1<<n)-1); } return 0; }

浙公网安备 33010602011771号