Doing Homework HDU - 1074
2018-06-17 21:49:27来源:未知 阅读 ()
Doing Homework HDU - 1074
题意:
有n个作业,每个作业有一个截止时间和完成所需时间,如果完成某个作业的时间超出了截止时间就扣完成时间-截止时间的分。求按怎样的顺序完成作业扣分最少。
方法:状压dp。ans[S]表示完成集合S的作业最少的扣分(集合S用一个数字表示)。pre[S]和pre2[S]分别表示由前一个状态到达状态S完成的作业序号、S的前一个状态。
首先应该意识到完成某个集合的作业,不管按照何顺序,总时间都是一样的。(曾经没发现导致没思路)
从小到大枚举S(这样的话枚举到每个集合时其去掉某个作业得到的集合保证都已经枚举到过,因为其子集的数字表示一定小于S)。
$ans[S]=min\{ans[S-p]+max(sumt[S]-d[p],0)\}$(p表示S集合内任意一项作业)
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<vector> 5 using namespace std; 6 typedef long long LL; 7 char name[16][110]; 8 LL d[16],c[16],ans[70000]; 9 LL pre[70000],pre2[70000]; 10 LL T,n,sumt; 11 vector<LL> vec; 12 int main() 13 { 14 LL i,j,t; 15 scanf("%lld",&T); 16 while(T--) 17 { 18 memset(name,0,sizeof(name)); 19 memset(ans,0x3f,sizeof(ans)); 20 memset(pre,0,sizeof(pre)); 21 memset(pre2,0,sizeof(pre2)); 22 scanf("%lld",&n); 23 for(i=1;i<=n;i++) 24 scanf("%s%lld%lld",name[i],&d[i],&c[i]); 25 ans[0]=0; 26 for(i=1;i<(1<<n);i++) 27 { 28 sumt=0; 29 for(j=1;j<=n;j++) 30 if(i&(1<<(j-1))) 31 sumt+=c[j]; 32 for(j=1;j<=n;j++) 33 if(i&(1<<(j-1))) 34 { 35 t=ans[i^(1<<(j-1))]+max(sumt-d[j],0LL); 36 if(t<=ans[i]) 37 { 38 ans[i]=t; 39 pre[i]=j; 40 pre2[i]=i^(1<<(j-1)); 41 } 42 } 43 } 44 printf("%lld\n",ans[(1<<n)-1]); 45 vec.clear(); 46 for(i=(1<<n)-1;i!=0;i=pre2[i]) 47 vec.push_back(pre[i]); 48 for(i=vec.size()-1;i>=0;i--) 49 printf("%s\n",name[vec[i]]); 50 } 51 return 0; 52 }
某题解
一个裸状态压缩~
题目大意: 一共有N门作业,三个数据是作业的名字,到期时间,和完成需要天数,完成做也期限超过一天扣一分.问以什么顺序完成作业可以使扣得分最少.如果有相同的分数名字按字典序排序.
状态转移方程: dp[i]=min(dp[j]+hw[k]-hwlast[k])+hw[k]; j为i中去掉第k个作业的状态,hw[k]为当前作业需要几天完成,hwlast为当前作业完成期限为多少,若(dp[j]+hw[k]<hwlast[k])则取零,表示状态不可用.
源代码:
#include <myhead.h> const int N=16; const int M=110; const int NUM=(1<<N); struct HomeWork { char name[M]; int last; int time; }; struct Dp { int timer; int scr; int last; int i; void init() { this->timer=0; this->scr=INT_MAX; this->last=0; this->i=0; } }; int n,num; HomeWork hw[N]; Dp dp[NUM]; void init() { scanf("%d",&n); num=(1<<n); dp[0].init(); dp[0].scr=0; for(int i=0;i<n;++i) { scanf("%s%d%d",hw[i].name,&hw[i].last,&hw[i].time); } } void work() { for(int i=1;i<num;++i) { dp[i].init(); for(int j=n-1;j>=0;--j) { int s=(1<<j); if(s&i) { int past=i-s; int t=dp[past].timer+hw[j].time-hw[j].last; checkmax(t,0); t+=dp[past].scr; if(t<dp[i].scr) { dp[i].scr=t; dp[i].i=j; dp[i].last=past; dp[i].timer=dp[past].timer+hw[j].time; } } } } stack<int> s; int star=num-1; while(star) { s.push(dp[star].i); star=dp[star].last; } printf("%d\n",dp[num-1].scr); while(!s.empty()) { printf("%s\n",hw[s.top()].name); s.pop(); } } int main() { int t; scanf("%d",&t); while(t--) { init(); work(); } return 0; }
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- HDU-2955-Robberies(0-1背包) 2020-03-30
- hdu1455 拼木棍(经典dfs) 2020-02-29
- anniversary party_hdu1520 2020-02-16
- hdu1062 text reverse 2020-01-27
- hdu4841 2020-01-26
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash