您的位置:首页 > 其它

HDU 1074 (状态压缩dp)详解

2016-08-10 17:01 387 查看
题目意思:Ignatius同学,快到期末了结果还有好多课程没有完成,每门课作业都有对应的截至日期,和完成它所需的时间,超过截至日期后,没多一天扣1分,现在文他该如何安排写作业的顺序使得被扣的分最少?

输入要求: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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dp HDU 状态压缩dp