zoukankan      html  css  js  c++  java
  • HDU 1074 Doing Homework (dp+状态压缩)

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

    题目大意:学生要完成各科作业, 给出各科老师给出交作业的期限和学生完成该科所需时间, 如果逾期一天则扣掉一单位学分, 要你求出完成所有作业而被扣最小的学分, 并将完成作业的顺序输出.

    Sample Input
    2
    3
    Computer 3 3
    English 20 1
    Math 3 2
    3
    Computer 3 3
    English 6 3
    Math 6 3
     
    Sample Output
    2
    Computer
    Math
    English
    3
    Computer
    English
    Math

    分析:(转)

    刚开始以为是背包, 但背包难以记录输出顺序, 所以只能换另一种DP方式, 这里科目最大数目才15, 只要有全枚举的思想来DP就可以解决了, 有一个专有名词叫状态压缩DP. 状态压缩DP采用二制进的思想,

          1, 0分别代表有或否.

        如:

        3的二进制为 11, 则代表完成了每一,二个科目的状态, 101代表完成了第一三两个科目的状态.

        这样, 可以从0->(1 << N)来获取所有状态, 并进行适当的状态转移. 对该题来说 D[s]代表集合s的状态,  要得到D[s]的状态, 可以从0 - N 分别检查是否在s集合内[s & (1 << i) > 0则表示i在集合s上,反之..], 如果i在s集合内, 刚D[s]可从D[s-{i}]来获得, [s-{i},可以s - (1<<i)来计算]. 这样表示在已完成了s-{i}的基础上再完成i后的装态, 遍历i, 取最优解.

    代码如下:

     1 # include<iostream>
     2 # include<cstdio>
     3 # include<string>
     4 # include<cstring>
     5 # include<stack>
     6 using namespace std;
     7 const int MAXN = 16;
     8 const int INF = 0xffffff;
     9 struct Homework{
    10     string name;
    11     int deadline;    //截止时间
    12     int time;    //完成时间
    13 }data[MAXN];
    14 
    15 struct {
    16     int time;    //完成该集合作业所需时间
    17     int score;    //完成该集合作业被扣学分
    18     int last;    //记录上一个位置
    19     int pos;    //记录当前位置
    20 }dp[1<<MAXN];    
    21 
    22 int main(){
    23     int T,n;
    24     int i;
    25     cin>>T;
    26     while(T--){
    27         cin>>n;
    28         for(i=0;i<n;i++)
    29             cin>>data[i].name>>data[i].deadline>>data[i].time;
    30         int endstate = 1<<n;
    31         int recent = 0;
    32         int reduce = 0;
    33         int past = 0;
    34         for(int S=1; S<endstate; S++){
    35             dp[S].score  = INF;
    36 
    37             for(i=n-1;i>=0;i--){
    38                 recent = 1<<i;
    39                 if(S & recent){
    40                     past = S - recent;    //余下的作业集合
    41                     reduce = dp[past].time + data[i].time - data[i].deadline;    //完成该作业被扣学分,小于0则不扣
    42                     if(reduce < 0)
    43                         reduce = 0;
    44                     if(reduce + dp[past].score < dp[S].score){
    45                         dp[S].time = dp[past].time + data[i].time;
    46                         dp[S].score = reduce + dp[past].score;
    47                         dp[S].pos = i;
    48                         dp[S].last = past;
    49                         
    50                     }
    51                 }
    52             }
    53         }
    54         stack<int >path;    //保存路径
    55         recent = endstate - 1;    //1<<n-1,表示n个1的2进制数,即全集
    56         while(recent){
    57             path.push(dp[recent].pos);
    58             recent = dp[recent].last;
    59         }
    60         cout << dp[endstate-1].score<<endl;
    61         while(!path.empty()){
    62             int top = path.top();
    63             cout<<data[top].name<<endl;
    64             path.pop();
    65         }
    66     }
    67     return 0;
    68 }
  • 相关阅读:
    vue-cli3配置开发环境和生产环境
    vue配置开发环境和生产环境
    js实现div拖拽互换位置效果
    axios用post提交的数据格式
    面试题会被问及哪些?(总结)
    深入理解vue
    nodejs 前端项目编译时内存溢出问题的原因及解决方案
    MUI框架开发HTML5手机APP(一)--搭建第一个手机APP
    关于if省略{}时的一些问题
    函数声明的两种形式的区别
  • 原文地址:https://www.cnblogs.com/acm-bingzi/p/3278900.html
Copyright © 2011-2022 走看看