• HDU1074


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

    题目大意:T个 test case。对于每个test case,有N门课的作业,对于每门课的作业,对应一个期限D和完成所需时间C。如果没有在期限D之前完成作业,那么每过一天扣一分,问怎么安排做作业的顺序才能使扣分最少。注意,1<=N<=15。

    解题思路:

      由于1<=N<=15,可以使用状态压缩DP。用 dp[i] 中的 i 记录已完成的作业,(例,i = 18 = 10010,代表其第2,5门作业已完成,而其他的则未完成,因为左数第2,5位上的数字为1)。

      状态转移方程:以 i 为外循环,在内循环遍历所有作业,对于一个 i ,如果第 j 门作业已经完成,那么不考虑,如果未完成,那么 dp[i|(1<<j)] = min( dp[i|(1<<j)], dp[i] + cal() ). cal()是一个用于计算加上这一门课程后要扣多少分的函数。

      仍然用 vector<int> path[ ] 记录路径。由于在给出课名的时候本身就是按照字典序排列的,而且我们的遍历顺序也是从 0 开始,所以对于里面的什么升序排列不用考虑。

      waring: 移位符号的优先级极低,所以很多时候都要加(),不然会出bug。

     1 #include <cstdio>
     2 #include <vector>
     3 using namespace std;
     4 const int maxn=1<<16;
     5 const int inf=0x7ffffff;
     6 vector<int> path[maxn];
     7 int dp[maxn];
     8 struct classes{
     9     char name[110];
    10     int D,C;
    11 }cs[20];
    12 int cal(int d,int ed){
    13     if(ed<=d)   return 0;
    14     return ed-d;
    15 }
    16 int main(){
    17     int T,N;
    18     scanf("%d",&T);
    19     while(T--){
    20         scanf("%d",&N);
    21         for(int i=0;i<N;i++){
    22             scanf("%s",cs[i].name);
    23             scanf("%d%d",&cs[i].D,&cs[i].C);
    24         }
    25         for(int i=0;i<(1<<N);i++){
    26             dp[i]=inf;
    27             path[i].clear();
    28         }
    29         dp[0]=0;
    30         int days;
    31         for(int i=0;i<(1<<N);i++){      //注意括号
    32             days=0;
    33             for(int j=0;j<N;j++){
    34                 if((1<<j)&i)            //括号
    35                     days+=cs[j].C;
    36             }
    37             for(int j=0;j<N;j++){
    38                 if((i&(1<<j))==0){      //i&(1<<j)外面一定要加括号
    39                     int ca=cal(cs[j].D,days+cs[j].C);
    40                     if(dp[i|(1<<j)]>dp[i]+ca){
    41                         path[i|(1<<j)]=path[i];
    42                         path[i|(1<<j)].push_back(j);
    43                         dp[i|(1<<j)]=dp[i]+ca;
    44                     }
    45                 }
    46             }
    47         }
    48         printf("%d
    ",dp[(1<<N)-1]);
    49         for(int i=0;i<path[(1<<N)-1].size();i++){
    50             int ind=path[(1<<N)-1][i];
    51             printf("%s
    ",cs[ind].name);
    52         }
    53     }
    54     return 0;
    55 }
    View Code
    “这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。”
  • 相关阅读:
    MyBatis学习笔记
    通过Executor来启动线程比用Thread的start()更好
    步骤2:JMeter 分布式测试(性能测试大并发、远程启动解决方案)
    步骤1:JMeter 录制脚本接口测试
    adb常用命令(手机测试)
    电商购物核心功能测试点
    APP测试基本流程以及APP测试要点
    Jmeter-jtl性能测试报告转换-2种导出方法
    Linux之find查找命令
    linux之top命令详解
  • 原文地址:https://www.cnblogs.com/Blogggggg/p/7276014.html
Copyright © 2020-2023  润新知