• [贪心,dp] 2019中国大学生程序设计竞赛(CCPC)


    题目:http://acm.hdu.edu.cn/showproblem.php?pid=6709

    Fishing Master

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
    Total Submission(s): 631    Accepted Submission(s): 170


    Problem Description
    Heard that eom is a fishing MASTER, you want to acknowledge him as your mentor. As everybody knows, if you want to be a MASTER's apprentice, you should pass the trial. So when you find fishing MASTER eom, the trial is as follow:

    There are n fish in the pool. For the i - th fish, it takes at least ti minutes to stew(overcook is acceptable). To simplify this problem, the time spent catching a fish is kminutes. You can catch fish one at a time and because there is only one pot, only one fish can be stewed in the pot at a time. While you are catching a fish, you can not put a raw fish you have caught into the pot, that means if you begin to catch a fish, you can't stop until after k minutes; when you are not catching fish, you can take a cooked fish (stewed for no less than ti) out of the pot or put a raw fish into the pot, these two operations take no time. Note that if the fish stewed in the pot is not stewed for enough time, you cannot take it out, but you can go to catch another fish or just wait for a while doing nothing until it is sufficiently stewed.

    Now eom wants you to catch and stew all the fish as soon as possible (you definitely know that a fish can be eaten only after sufficiently stewed), so that he can have a satisfying meal. If you can complete that in the shortest possible time, eom will accept you as his apprentice and say "I am done! I am full!". If you can't, eom will not accept you and say "You are done! You are fool!".

    So what's the shortest time to pass the trial if you arrange the time optimally?
     

     

    Input
    The first line of input consists of a single integer T(1T20), denoting the number of test cases.

    For each test case, the first line contains two integers n(1n105),k(1k109), denoting the number of fish in the pool and the time needed to catch a fish.

    the second line contains n integers, t1,t2,,tn(1ti109) ,denoting the least time needed to cook the i - th fish.
     

     

    Output
    For each test case, print a single integer in one line, denoting the shortest time to pass the trial.
     

     

    Sample Input
    2 3 5 5 5 8 2 4 3 3
     

     

    Sample Output
    23 11
    Hint
    Case 1: Catch the 3rd fish (5 mins), put the 3rd fish in, catch the 1st fish (5 mins), wait (3 mins), take the 3rd fish out, put the 1st fish in, catch the 2nd fish(5 mins), take the 1st fish out, put the 2nd fish in, wait (5 mins), take the 2nd fish out. Case 2: Catch the 1st fish (4 mins), put the 1st fish in, catch the 2nd fish (4 mins), take the 1st fish out, put the 2nd fish in, wait (3 mins), take the 2nd fish out.
     

     

    Source
     

     

    Recommend
    liuyiding   |   We have carefully selected several similar problems for you:  6712 6711 6710 6709 6708 

    题意:

    有n条鱼,第i条鱼至少要被炖ti分钟(可以超过ti),钓一条鱼恰好需要k分钟(不能少于k分钟也不能大于k分钟且中途不能停止)
    钓了鱼可以无限存鱼,但每次只能炖一条鱼且中途不能停止(鱼放进锅里后必须被炖ti分钟),在炖鱼时可以去钓鱼或等待,鱼炖好后可以立刻(不花时间)地拿出鱼或放进鱼
    问钓完并炖完这些鱼最少要花费多少分钟

    思路:

    先考虑最理想的情况,只需额外花费钓一条鱼的时间,剩下的时间都用来炖鱼,也就是ans=k+Σti,这样是能充分利用时间的,因为在炖鱼的时候就可以钓鱼,每次炖鱼时可钓的鱼的数量为[ti/k],
    但这种时候存在Σ[ti/k]<n-1的情况(n-1是因为第一次已经钓了一条鱼),也就是在炖鱼时不能把全部鱼都钓完,那么这样就会造成时间的浪费,为了使浪费的时间之和最少,我们需要先
    搞清楚每次最少会浪费多少时间,现在炖鱼时可以钓[ti/k]条鱼,但可能不会重复利用到炖鱼的时间,还要等待ti%k的时间,但现在无法在炖鱼的时间钓完所有鱼,还需要钓need=n-1-Σ[ti/k]条鱼,
    现在考虑要额外花时间去钓鱼,可以额外花need*k的时间去钓鱼,或在某些炖鱼时等待ti%k的时间时拿去钓鱼,因为钓鱼需要k分钟且不能停止,但现在ti%k时间后炖鱼才会停止,所以我们需要浪费k-ti%k时才能继续炖鱼,
    可以发现k>k-ti%k,显然后者方案更优,所以如果我们需要额外钓need条鱼,则选前need小的k-ti%k去浪费,也就是对浪费时间排好序后把前need个浪费时间加到中ans最后输出ans就好了

    比赛时在这个样例出了问题:


    input:

    1
    3 500
    999 20 20

    output:

    1540

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int amn=1e5+5;
     4 int t[amn],waste[amn];
     5 int main(){
     6 //    cout<<500-(999%500);
     7     int T,n,k;
     8     long long ans,cancatch;
     9     scanf("%d",&T);
    10     while(T--){
    11         scanf("%d%d",&n,&k);
    12         ans=k;cancatch=0;       ///第一次必须要花k分钟去抓鱼,总时间初始化为k,在炖鱼时间钓鱼数量初始化为0
    13         for(int i=0;i<n;i++){
    14             scanf("%d",&t[i]);
    15             ans+=t[i];          ///总时间加上炖鱼时间
    16             cancatch+=t[i]/k;   ///炖鱼时间钓鱼数量+=t[i]/k
    17             waste[i]=k-t[i]%k;  ///每次浪费时间=k-t[i]%k
    18         }
    19         if(cancatch<n-1){       ///如果炖鱼时没有掉完全部的鱼
    20             int need=n-1-cancatch;      ///need为还需要钓的鱼
    21             sort(waste,waste+n);        ///给浪费时间排序,取前need小的浪费时间加入总时间
    22             for(int i=0;i<need;i++)ans+=waste[i];
    23         }
    24         printf("%lld
    ",ans);
    25     }
    26 }
    27 /**
    28 有n条鱼,第i条鱼至少要被炖ti分钟(可以超过ti),钓一条鱼恰好需要k分钟(不能少于k分钟也不能大于k分钟且中途不能停止)
    29 钓了鱼可以无限存鱼,但每次只能炖一条鱼且中途不能停止(鱼放进锅里后必须被炖ti分钟),在炖鱼时可以去钓鱼或等待,鱼炖好后可以立刻(不花时间)地拿出鱼或放进鱼
    30 问钓完并炖完这些鱼最少要花费多少分钟
    31 
    32 先考虑最理想的情况,只需额外花费钓一条鱼的时间,剩下的时间都用来炖鱼,也就是ans=k+Σti,这样是能充分利用时间的,因为在炖鱼的时候就可以钓鱼,每次炖鱼时可钓的鱼的数量为[ti/k],
    33 但这种时候存在Σ[ti/k]<n-1的情况(n-1是因为第一次已经钓了一条鱼),也就是在炖鱼时不能把全部鱼都钓完,那么这样就会造成时间的浪费,为了使浪费的时间之和最少,我们需要先
    34 搞清楚每次最少会浪费多少时间,现在炖鱼时可以钓[ti/k]条鱼,但可能不会重复利用到炖鱼的时间,还要等待ti%k的时间,但现在无法在炖鱼的时间钓完所有鱼,还需要钓need=n-1-Σ[ti/k]条鱼,
    35 现在考虑要额外花时间去钓鱼,可以额外花need*k的时间去钓鱼,或在某些炖鱼时等待ti%k的时间时拿去钓鱼,因为钓鱼需要k分钟且不能停止,但现在ti%k时间后炖鱼才会停止,所以我们需要浪费k-ti%k时才能继续炖鱼,
    36 可以发现k>k-ti%k,显然后者方案更优,所以如果我们需要额外钓need条鱼,则选前need小的k-ti%k去浪费,也就是对浪费时间排好序后把前need个浪费时间加到中ans最后输出ans就好了
    37 
    38 比赛时在这个样例出了问题:
    39 input:
    40 
    41 1
    42 3 500
    43 999 20 20
    44 
    45 output:
    46 
    47 1540
    48 
    49 **/
  • 相关阅读:
    LeetCode: Text Justification 解题报告
    LeetCode: Evaluate Reverse Polish Notation 解题报告
    telnet服务搭建
    CentOS 7 快速部署 ELK
    CSVN配置自动备份策略
    使用mysqlproxy实现mysql读写分离
    linux挂载windows共享文件夹
    Centos7.3使用花生壳映射端口
    rpm使用
    linux运维注意事项
  • 原文地址:https://www.cnblogs.com/Railgun000/p/11403678.html
Copyright © 2020-2023  润新知