HDU Doing Homework

据说是状态压缩DP,我用bfs()做了,其实思想是一样的,下面是我的代码:仅供参考。

 

 1  // 此题可用二进制表示所有的状态,一个进制数的每一位对应一种作业,如果是1表示做这种作业,
 2  // 但是还有个先做哪种作业的顺序,此时可以先让每一位都为1为第一种状态,到下一种状态时,
 3  // 可以把一个0变为1,表示下来做这种作业,如果遇到过这种状态,但先后顺序不一样,则保留最优解,
 4  // 可以举个例子,比如有三种作业,那么最初的状态为{(001) (010) (100)} 分别表示先做标记为1的作业,
 5  // 则下一个状态便为: (001) -> { (011) , (101) }  (010) -> {(110) , (011)}; (100) ->{ (101), (110) }
 6  // 有相同的状态则会记录最优的一个状态,超时最少的,下来就到最后一种状态(111), (111)状态先取最优的即为结果
 7 #include <iostream>
 8 #include <cstring>
 9 #include <queue>
10 #include < string>
11  using  namespace std;
12  const  int N =  1<< 16;
13  // visit标记状态有没有访问过 
14  // a记录超过的最短时间  b记录写作业一共花费的时间  
15  // pre记录作业的先后顺序,回溯输出结果
16  bool visit[N];  int a[N], b[N], pre[N];
17  struct Node{
18      string sub;   // 科目
19      int ed, t; // 结束时间、持续时间
20 }Sub[ 16];
21 
22  void f( int p){ // 回溯输出结果
23      if(pre[p] == - 1return;
24      else{
25          int t = pre[p];  t = p ^ ( 1<<t);
26         f(t);
27         cout<<Sub[pre[p]].sub<<endl;
28     }
29 }
30  int bfs( int n){
31     memset(visit,  falsesizeof(visit));
32     memset(a,  0sizeof(a));
33     memset(pre,  0sizeof(pre));
34     queue< int> q;
35      int i, j, t1, t2;
36     pre[ 0] = - 1;
37      for(i =  0; i < n; ++i){   // 初始化每种作业为初状态
38         j =  1 << i;
39         q.push(j); pre[j] = i; b[j] = Sub[i].t;
40          if(Sub[i].t <= Sub[i].ed) a[j] =  0;
41          else a[j] = Sub[i].t - Sub[i].ed;
42         visit[j] =  true;
43     }
44      while(!q.empty()){
45         t1 = q.front(); q.pop();
46          for(i =  0; i < n; ++i){
47             j =  1 << i; t2 = t1 & j;  // 判断此作业是否做过,做过为1,未做过为0
48              if( !t2 ){
49                 t2 = t1 | j; // 下一种状态
50                  if(!visit[t2]){  // 没有访问过此状态
51                     visit[t2] =  true;  b[t2] = b[t1] + Sub[i].t;
52                      if(b[t2] > Sub[i].ed) a[t2] = a[t1] + b[t2] - Sub[i].ed;
53                      else a[t2] = a[t1];
54                     q.push(t2);  pre[t2] = i;
55                 } else{
56                      int s1 = b[t1] + Sub[i].t;
57                      if(s1 > Sub[i].ed) s1 = a[t1] + s1 - Sub[i].ed;
58                      else s1 = a[t1];
59                      if(a[t2] > s1){
60                         a[t2] = s1; b[t2] = b[t1] + Sub[i].t;
61                         q.push(t2); pre[t2] = i;
62                     }
63                 }
64             }
65         }
66     } cout<<a[t1]<<endl;  f(t1);
67 }
68 
69  int main(){
70      int t, N, i;
71     cin>>t;
72      while(t--){
73         cin>>N;
74          for(i =  0; i < N; ++i)
75         cin>>Sub[i].sub>>Sub[i].ed>>Sub[i].t;
76         bfs(N);
77     }
78      return  0;
79 }
View Code

 

转载于:https://www.cnblogs.com/yaling/p/3232219.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值