hdu1074Doing Homework(状压dp)

本文提供了一道关于作业调度问题的详细解答。通过状态压缩的方法,解决了一个包含不超过15个作业的任务,每个作业有不同的截止时间和完成时间,目标是找到一种最优的完成方式,使得总罚分最少。

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1074

题意:n个作业,截止时间di,需要ci时间做完,每超过截止时间一天罚一分,问最少罚多少分。

1<=N<=15,状态压缩。

 1 #include<cstdio>
 2 #include<cstring>
 3 const int maxn=16;
 4 int dp[1<<maxn],t[1<<maxn],pre[1<<maxn];
 5 int d[maxn],c[maxn];
 6 char s[maxn][120];
 7 int n;
 8 void print(int x)
 9 {
10     if(x==0) return ;
11     print(pre[x]);
12     x-=pre[x];
13     for(int i=0;i<n;i++)
14         if(x&1<<i) puts(s[i]);
15 }
16 int main()
17 {
18     int tt;
19     scanf("%d",&tt);
20     while(tt--)
21     {
22         int cost;
23         scanf("%d",&n);
24         memset(dp,0x3f,sizeof(dp));   //之前还没这么用过,一直以为只能赋0和1
25         for(int i=0;i<n;i++)
26             scanf("%s%d%d",s[i],&d[i],&c[i]);
27         dp[0]=t[0]=0;  //初始罚分为0;
28         int m=1<<n;     
29         for(int i=1;i<m;i++)   //枚举所有补过的作业状态,1为补过,0为未补
30             for(int j=0;j<n;j++)   //按位寻找合法前驱
31         {
32             if((i&1<<j)==0) continue;
33             int k=i-(1<<j);  //k是前驱状态
34             t[i]=t[k]+c[j];  //从状态k到i(这次做j号作业),到此一共耗时为t[k]+c[j]
35             cost=t[i]-d[j]>0?t[i]-d[j]:0;  //计算罚分
36             if(dp[i]>=dp[k]+cost)   // 用>=是为了最小字典序
37             {
38                 dp[i]=dp[k]+cost;
39                 pre[i]=k;   //记录前驱状态
40             }
41         }
42         printf("%d\n",dp[m-1]);
43         print(m-1);  //递归打印
44     }
45 }

 

转载于:https://www.cnblogs.com/yijiull/p/6606483.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值