Doing Homework HDU - 1074
Posted Jozky86
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Doing Homework HDU - 1074相关的知识,希望对你有一定的参考价值。
题意:
有n个任务,每个任务有一个截止时间,超过截止时间一天,要扣一个分。
求如何安排任务,使得扣的分数最少。
(1<=n<=15)
题解:
n很小,可以往状压dp方向去想
我们用i枚举所有的状态,然后对于第j个任务,tmp=i-(1<<j),tmp表示状态i在未完成j的前一个状态
tim[]表示当前状态所花费的时间,那么完成第j个任务所扣分数为score=tim[tmp]+cost[j]-dead[j],完成tmp所需时间+完成任务j所需时间-截止日期,超出多少扣多少分数
dp[i]表示i状态下的的最小扣分,dp[i]=min(dp[tmp]+score)
为了方便答案的输出,我们用pre[i]记录,最后一个完成状态i所办的任务,pre[i]=j,这样记录是为了之后方便输出,w=i-(1<<pre[i])就是在任务j之前的状态,然后依次寻找w-(1<<pre[w])
在循环任务j时,要从后向前找,因为题目所给的数据是字典序递增的,而我们最后的输出是根据pre倒着输出的,所以逆着寻找可以保证输出的字典序最小
代码:
我的代码不知道哪里错了,一直wa,先贴上网上的正代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstdlib>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<ctime>
#include<vector>
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define N 15
#define MOD 10007
#define E 1e-6
#define LL long long
using namespace std;
char str[20][101];
int dp[1<<N],pre[1<<N],times[1<<N];
int dead[N],cost[N];
void print(int x){//递归输出作业顺序
if(!x)
return;
print(x-(1<<pre[x]));
printf("%s\\n",str[pre[x]]);
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%s%d%d",&str[i],&dead[i],&cost[i]);
memset(times,0,sizeof(times));
memset(pre,0,sizeof(pre));
for(int i=1;i<(1<<n);i++){//枚举所有状态
dp[i]=INF;//初始化状态i的扣分
for(int j=n-1;j>=0;j--){//从后向前找
int temp1=1<<j;
if(!(i&temp1))//状态i不存在作业j完成的情况
continue;
int temp2=i-temp1;//未完成作业j的状态
int score=times[temp2]+cost[j]-dead[j];//计算扣分
if(score<0)//最小扣分为0
score=0;
if(dp[i]>dp[temp2]+score){
dp[i]=dp[temp2]+score;//记录最小扣分
times[i]=times[temp2]+cost[j];//到达状态i所花费的时间
pre[i]=j;//状态i的前驱
}
}
}
printf("%d\\n",dp[(1<<n)-1]);
print((1<<n)-1);
}
return 0;;
}
以上是关于Doing Homework HDU - 1074的主要内容,如果未能解决你的问题,请参考以下文章
[2016-03-28][HDU][1074][Doing Homework]