您的位置:首页 > 其它

hdu 1074 Doing Homework(状态压缩dp)

2016-03-21 21:33 471 查看

Doing Homework

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=1074

解题思路:

题目大意:

有n门课程作业,每门作业的截止时间为D,需要花费的时间为C,若作业不能按时完成,每超期1天扣1分。这n门作业按课程的字典

序先后输入。

问完成这n门作业至少要扣多少分,并输出扣分最少的做作业顺序。

PS:达到扣分最少的方案有多种,请输出字典序最小的那一组方案。

算法思想:

因为最多只有15门课程,可以使用二进制来表示所有完成的状况。

例如5,二进制位101,代表第一门和第三门完成了,第二门没有完成,那么我们可以枚举1~1<<n便可以得出所有的状态。

然后对于每一门而言,其状态是t = 1<<i,我们看这门在现在的状态s下是不是完成,可以通过判断s&t是否为1来得到。

当得出t属于s状态的时候,我们便可以进行dp了,在dp的时候要记录路径,方便之后的输出。

AC代码:

#include <bits/stdc++.h>
using namespace std;

const int INF = 0x3f3f3f3f;

struct Course{
string name;
int deadline,cost;
}course[50];

struct node{
int score,now,pre,time;
}dp[1<<15];

int main(){
int T;
scanf("%d",&T);
while(T--){
int n;
memset(dp,0,sizeof(dp));
scanf("%d",&n);
for(int i = 0; i < n; i++)
cin >> course[i].name >> course[i].deadline >> course[i].cost;
int sum = 1<<n;
for(int i = 1; i < sum; i++){
dp[i].score = INF;
for(int j = n-1; j >= 0; j--){
int tmp = 1<<j;
if(i & tmp){
int past = i-tmp;
int st = dp[past].time+course[j].cost-course[j].deadline;
if(st < 0)
st = 0;
if(st+dp[past].score < dp[i].score){
dp[i].score = st+dp[past].score;
dp[i].now = j;
dp[i].pre = past;
dp[i].time = dp[past].time+course[j].cost;
}
}
}
}
stack<int> s;
int tmp = sum-1;
cout << dp[tmp].score << endl;
while(tmp){
s.push(dp[tmp].now);
tmp = dp[tmp].pre;
}
while(!s.empty()){
cout << course[s.top()].name << endl;
s.pop();
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: