zoukankan      html  css  js  c++  java
  • 《训练指南》——6.13

      困于时间缘故和考试缠身,笔者在先前关于《训练指南》的而第二章的数学基础的介绍先告一段落,开始对第一章简单的一些算法基础题目进行介绍。

      Uva11292:

      你的王国里有一条n个头的恶龙,你希望雇一些其实把它杀死(即砍掉所有的头)。村里有m个其实可以雇佣,一个能力值为x的其实可以砍掉恶龙一个半径不超过x的头,且需要支付x个金币。如何雇佣其实才能砍掉恶龙的所有头,且需要支付的金币最少?注意,一个其实只能看一个头(且只能被雇用一次)。

      分析:观察到题目给出支付最少的字眼,我们容易将其往动态规划或者贪心的算法思想上靠拢,而如果有一定动态规划基础的读者,可能会和笔者一样,认为它非常近似01背包的模型。

      那么我们继续对比一下两个模型参量的区别看是否能够建立起联系,对于我们熟悉的01背包模型,即有n个价值、体积已知的物体,装入一个容积为v的背包,我们能够找到使得价值之和最大的方案,其主要的特征就是有n个物体,每个物体两个维度的参量(价值、体积),然后给出一个参量的限制(背包的体积,进一步抽象这个参量,可将其理解为费用),求解另一个参量的最值。

      那么我们反过来看这道题目,m个人,有两个维度的参量:费用和能力。而对于n头龙,显然明显与01背包中容积为v的背包有着本质的区别,它会限制对勇士的选取,即不像01背包当中任何一个物体都可以放入背包,因此这里如果用01背包处理,仿佛并不是那么容易。

      其实上面这个过程刻意将这个问题的思考复杂化了,其实这道问题很简单,它其实就基于一种最简单的贪心策略,然后会用到分而治之当中所谓“表示变更”(《算法谜题》当中有过介绍),我们只需要对m个勇士的能力进行从小到大排序,然后从能力较小者依次往后选取能够砍掉一个头的勇士即可。

      简单的参考代码如下:

      #include<cstdio>
    
    #include<algorithm>
    
    #include<cstring>
    
    using namespace std;
    
    const int maxn = 20005;
    
    int main()
    
    {
    
         int boss[maxn],fighter[maxn];
    
         int n , m;
    
         while(scanf("%d %d",&n,&m) && (m || n))
    
         {
    
             for(int i = 1;i <= n;i++)
    
                  scanf("%d",&boss[i]);
    
             for(int i = 1;i <= m;i++)
    
                  scanf("%d",&fighter[i]);
    
             sort(boss + 1 , boss + n + 1);
    
             sort(fighter + 1 , fighter + m + 1);
    
     
    
     
    
            int index = 1;
    
            int sum = 0;
    
            for(int i = 1;i <= m;i++)
    
            {
    
                    for(int j = index;j <= n;j++)
    
                    {
    
                        if(fighter[i] >= boss[j])
    
                           {
    
                               index++;
    
                               sum += fighter[i];
    
                                break;
    
                           }
    
     
    
                    }
    
                    if(index == n + 1)
    
                          break;
    
            }
    
            if(index == n + 1)
    
                  printf("%d
    ",sum);
    
            else
    
                  printf("Loowater is doomed!
    ");
    
     
    
         }
    
    }

    Uva 11729:

      你有n个部下,每个部下需要完成一项任务。第i个部下需要你花Bi分钟交代任务,然后他会立刻独立的、无间断地执行Ji分钟后完成任务。你需要选择交代任务的顺序,是的所有任务今早执行完毕。注意,不能同时给两个部下交代任务,但部下们可以同时执行他们各自的任务。那么请问对于每组数据,输出完成任务的最短时间。

      分析:基于一个时间区段上去思考这个问题。每个人所占有的时间区段分成两部分,交代任务和做任务。由于题设的限制,交代任务的区段是不可能重合的,那么这里我们考虑贪心策略,显然是让做任务区段最长的先去做任务,我们整个过程表述成如下的伪代码:

      定义cost_time[i]是完成i个任务所有的最少时间

      for i 1 to num_of_person

          cost_time[i] = max(cost_time[i-1] , cost_time[i-1] – Ji[i-1]+ J[i] + B[i])

      简单的参考代码如下(思路很清晰但是就是A不了,测了多组数据也能过,想扔在这里吧):

    #include<cstdio>
    
    #include<algorithm>
    
    using namespace std;
    
    const int maxn  = 1005;
    
     
    
    struct person
    
    {
    
        int B , J;
    
    };
    
     
    
    bool cmp(person a , person b)
    
    {
    
         return a.J >= b.J;
    
    }
    
    int main()
    
    {
    
        struct person p[maxn];
    
        int n;
    
        int tt = 1;
    
        while(scanf("%d",&n) && n != 0)
    
        {
    
             for(int i = 1;i <= n;i++)
    
             {
    
                   scanf("%d%d",&p[i].B,&p[i].J);
    
             }
    
             sort(p + 1 , p + n + 1 , cmp);
    
            // printf("%d %d %d",p[1].J,p[2].J,p[3].J);
    
     
    
             int cost_time = p[1].B + p[1].J;
    
             for(int i = 2;i <= n;i++)
    
             {
    
                  cost_time = max(cost_time , cost_time - p[i-1].J + p[i].J + p[i].B);
    
                  //  printf("%d ",cost_time);
    
             }
    
             printf("Case %d: %d
    ",tt++,cost_time);
    
        }
    
    }       
  • 相关阅读:
    CS224n笔记12 语音识别的end-to-end模型
    Vue组件
    关于网站
    Vue问题区
    数组的增、删、改、查
    Tree全部展开/折叠
    python 中UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-7: ordinal not in range(128)的解决方法
    python安装wxPython
    python中的迭代器和生成器
    python中的re正则表达式和模板系统
  • 原文地址:https://www.cnblogs.com/rhythmic/p/5585455.html
Copyright © 2011-2022 走看看