HDU 1074 (状态压缩dp)详解
2016-08-10 17:01
387 查看
题目意思:Ignatius同学,快到期末了结果还有好多课程没有完成,每门课作业都有对应的截至日期,和完成它所需的时间,超过截至日期后,没多一天扣1分,现在文他该如何安排写作业的顺序使得被扣的分最少?
输入要求:T组数据,N门课,每门课的截至日期和完成所需的时间
输出要求:被扣的分,和写作业的顺序。(如果有不同顺序扣分相同的出现,输出字典序)
题目提示:1.因为最多只有15门课,所以1<<15在一个可以接受的范围内,但是15!太大,用枚举必定超时
2.输入时是按照字典序输入的
输入要求:T组数据,N门课,每门课的截至日期和完成所需的时间
输出要求:被扣的分,和写作业的顺序。(如果有不同顺序扣分相同的出现,输出字典序)
题目提示:1.因为最多只有15门课,所以1<<15在一个可以接受的范围内,但是15!太大,用枚举必定超时
2.输入时是按照字典序输入的
#include <iostream> #include <cstring> #include <stack> #include <algorithm> using namespace std; const int INF=0x3f3f3f3f;//四个3f struct node { string name; int deadline; int cost; } homework[20]; struct kode { int time;//记录时间 int score;//此时被扣的分 int pre;//它上面的一门课的编号 int now;//现在这门课的编号 } dp[1<<15]; int main() { int T; int i,j; int s,n,end; scanf("%d",&T); while(T--) { memset(dp,0,sizeof(dp)); scanf("%d",&n); for(i=0; i<n; i++)//建议从0开始,因为状态dp 1.....1最后一个1为2的0次方 { cin>>homework[i].name>>homework[i].deadline>>homework[i].cost; } end=1<<n; for(s=0;s<=end-1;s++)//end-1=1....1 n个1 代表所有作业已经完成了的状态 0代表没有作业完成 必须从小到大, //后面需要利用前面求出来的temp1+dp[past].score<dp[s].score { int temp;//用来记录现在是选择第i门课时的状态 dp[s].score=INF;//因为要求最小值,所以刚开始把他们初始化为无限大 dp[0].score=0;//初始化,做第一门课之前时间为0; for(i=n-1;i>=0;i--)//因为要求字典序输出,所以必须从大到小 //假设有两门课,完全相同,因为输入时是按照字典序输入的,所以开头字母大的必定序号大 //然后现进行判断,因为状态是从小往大递增的,刚开时小的已经进入,当状态大到两者都包括时,序号大的课,先进入该状态 //然后再到序号小的,而到序号小的时候因为他们截至日期和耗费时间完全一样下面的 //temp1+dp[past].score==dp[s].score因此的序号大的位置不改变,但输出时是按照状态从小到大输的,所有序号小的仍然在前面 { temp=1<<i;//0...100...000,1距离最右边有i个数位 if(s&temp)//如果s的第i位也为0,也就是该状态下,包含第i个门课,就进入if { int past=s-temp;//s-i //例如000011111 // 000010000 // =000001111刚好就是不学第i门课时的状态 int temp1=dp[past].time+homework[i].cost-homework[i].deadline; //之前的时间加上这门课需要耗费的时间 if(temp1<0)//因为有的课会提前完成,提前完成意味着不扣分,所以为0 { temp1=0; } if(temp1+dp[past].score<dp[s].score)//如果先做这门课,比之前的情况更少扣分,那么记录下来 { dp[s].now=i; dp[s].pre=past; dp[s].score=dp[past].score+temp1; dp[s].time=dp[past].time+homework[i].cost;//记录时间 } } } } stack<int> S;//构造一个栈 int temp2=end-1; cout << dp[temp2].score << endl; while(temp2) { S.push(dp[temp2].now);//将i门课的学习顺序以此存入栈中 temp2=dp[temp2].pre; } while(!S.empty()) { cout << homework[S.top()].name << endl;//因为刚才放的时候,全部学完时的状态在最下面,最上面是s=1时,那门课的序列 S.pop(); } } return 0; }
相关文章推荐
- 详解Android应用中屏幕尺寸的获取及dp和px值的转换
- 基于Android中dp和px之间进行转换的实现代码
- Android中dip、dp、sp、pt和px的区别详解
- LFC1.0.0 版本发布
- Android dpi,dip,dp的概念以及屏幕适配
- Android px、dp、sp之间相互转换
- HP data protector软件学习1--基本角色与基本工作流程
- HP data protector软件学习2--软件组成与界面介绍
- android中像素单位dp、px、pt、sp的比较
- Android对px和dip进行尺寸转换的方法
- 关于UI切图与开发 px和dp
- 【HDU 5366】The mook jong 详解
- 【HDU 2136】Largest prime factor 详细图解
- 【HDU 1568】Fibonacci 数学公式 详解
- Android根据分辨率进行单位转换-(dp,sp转像素px)
- android 尺寸 dp,sp,px,dip,pt详解
- DP问题各种模型的状态转移方程
- HDU 1568
- HDU1290
- POJ-1695-Magazine Delivery-dp