zoukankan      html  css  js  c++  java
  • 线段区间的覆盖

    i表示x轴上坐标为[i-1,i]的区间(区间长度为1),并给出M个不同的整数来表示M个这样的区间。现在要求画出几条线段覆盖住所有的区间,条件是:每条线段可任意长,但要求所画线段长度之和最小,并且线段的数目不超过N

    举例:给出M=61,2,4,5,7,11,分别表示6个长度为1的区间,要求用不超过N=3条线段将其覆盖。

    线段区间的覆盖问题

    上图给出了一种可行的覆盖方案,用三段长线段覆盖住6个长度为1的小线段,使得3短线段长度之和最小。

    l  算法思想

    运用贪心算法,M个线段会产生M-1个间断,间断有大有小,按照从大到小的顺序把线段间的间隔排好。假设初始状态下有一整条线段覆盖整个区域,每一步都从间隔最大的位置上断开该线段,直至断开N-1次,此时一整条线段就被分成了N截且这N截线段的长度和最小。

    l  程序模型的建立与设计流程

    如果N>=M,显然用M条长度为1的线段就可覆盖所有区间,所求的线段总长度也就为M。如果N,要另想办法。

    ①  N=1,那么所需线段总长为position[M-1]-position[0]+1;

    ②  N=2,那么相当于把①中的长线段分成两截。找到最大距离distance[i]=position[i]-position[i-1]-1 (1

    ③  N=3,同理,将distance第二大的位置断开,于是便形成3截线段,并且长度和最小。

    ④  N=k(k>1)时,只要在N=k-1时最小总长的覆盖方案下,找到被同一条线段覆盖最大的两个区间,“贪心”地从间隔处断开并适当调整两条线段的端点,就可以得到总长最小的方案。

    l  数据结构的选用

    可用整型数组position[M]表示所有的区间,并假设position[M]已按从小到达的顺序排好了。

    l  源程序编码清单

    #include

    using namespace std;

    const int SIZE=200;

     

    void Sort(int value[],int nNumber)              //nNumber个值从大到小排列

    {

           for(int i=0;i

                  for(int j=0;j

                         if(value[j]

                         {

                                int temp=value[j];

                                value[j]=value[j+1];

                                value[j+1]=temp;

                         }

    }

    void main()

    {

           int M=0;

           int position[SIZE];

           cout<<"请输入待覆盖的区间总数M="<<endl;

           cin>>M;

           int i=0;

           cout<<"请具体地输入第"<<M

                  <<"个要覆盖的区间:"<<endl;

           for(i=0;i

           {

                  cin>>position[i];

           }

           Sort(position,M);

     

           int distance[SIZE-1];

           for(i=0;i

                  distance[i]=position[i]-position[i+1]-1;

           Sort(distance,M-1);

     

           int N=1;                                     //可用于覆盖的线段总数

           cout<<"请输入可用于覆盖的线段总数N="<<endl;

           cin>>N;

    //**********贪心算法*************************

           if(N>=M)

           {

                  cout<<"最小的线段总长为"

                         <<M<<endl;

                  return;                           

           }

     

           else if(N

           {

                  int nLine=1;                           //记录当前线段总数

                  int nTotalLength=position[0]-position[M-1]+1;//记录当前情况下所用线段的总长

                  int nDivide=0;                         //记录当前最大的未断开的区间位置

                  while((nLine0]))

                  {

                         nLine++;

                         nTotalLength-=distance[nDivide];

                         nDivide++;

                  }

                  cout<<"最小的线段总长为"

                         <<nTotalLength<<endl;

           }

    }

    l  程序输入、输出

    线段区间的覆盖问题

    l  时间与空间复杂度分析

    算法时间复杂度为O(nlogn)+O(n)。

    l  程序使用说明

    ①  对position的排序无论从大到小还是从小到大没有区别,不影响区间距离的计算。

    ②  注意while循环的两个条件

    l  总结与完善

    这个程序可以得到最小总长条件下所需的最少线段的数目,但并不能给出这些线段的端点信息。可以进一步对程序修改以添加此功能。

  • 相关阅读:
    SOFT-NMS (二) (non maximum suppression,非极大值抑制)
    NMS(non maximum suppression,非极大值抑制)
    读取txt文件的数据,并将其转换为矩阵
    x.append()增加不同维度的区别
    in __init__ self._traceback = tf_stack.extract_stack()的一个原因
    LoadRunner系列之—-03 用Java Vuser协议编写接口测试脚本
    WebLogic篇----02 控制台性能监控
    soapUI系列之—-01 介绍soapUI简介,groovy 简介
    oracle获取字符串长度函数length()和lengthb()
    soapUI系列之—-06 testrunner实现自动化测试
  • 原文地址:https://www.cnblogs.com/bytebull/p/5733956.html
Copyright © 2011-2022 走看看