在这样的塔中寻找尽可能多的人

时间:2010-12-12 22:57:56

标签: algorithm

首先,让我们看看问题,

马戏团正在设计一个由彼此站立的人组成的塔式例程 肩膀。出于实际和美学的原因,每个人必须比他或她下面的人更短更轻。考虑到马戏团中每个人的身高和体重,编写一种计算最大可能人数的方法 在这样一座塔楼里。

EXAMPLE:
Input:
        (ht, wt): (65, 100) (70, 150) (56, 90) (75, 190) (60, 95) (68, 110)
Output: The longest tower is length 6 and includes from top to bottom: 
        (56, 90) (60,95) (65,100) (68,110) (70,150) (75,190)

但我不太明白解决方案如下:

本书提出的解决方案:

  • 步骤1.按高度对所有项目进行排序 首先,然后按重量。这意味着 如果所有的高度都是独特的, 那么这些项目将按照排序 他们的身高。如果高度是 同样,物品将按其分类 重量。示例:»»排序前: (60,100)(70,150)(56,90)(75, 190)(60,95)(68,110)。 “后 排序:(56,90),(60,95), (60,100),(68,110),(70,150), (75190)。
  • 步骤2.找到最长的序列 其中包含越来越高的高度 增加重量。为此,我们:

  • a)从中间开始 序列。目前,max_sequence是 空。

  • b)如果,对于下一个项目, 身高和体重不大 比上一个项目,我们
    将此项目标记为“不合适”

    c)如果 发现的序列比项目多 “最大序列”,它变成“最大 序列”。

  • d)之后搜索是 从“不合适的项目”重复,
    直到我们到达结束 原始序列。

    public class Question {
    ArrayList<HtWt> items;
    ArrayList<HtWt> lastFoundSeq;
    ArrayList<HtWt> maxSeq;
    
    
    / Returns longer sequence
    ArrayList<HtWt> seqWithMaxLength(ArrayList<HtWt> seq1, ArrayList<HtWt> seq2) {
        return seq1.size() > seq2.size() ? seq1 : seq2;
    }
    
    
    // Fills next seq w decreased wts&returns index of 1st unfit item.
    int fillNextSeq(int startFrom, ArrayList<HtWt> seq) {
      int firstUnfitItem = startFrom;
      if (startFrom < items.size()) {
          for (int i = 0; i < items.size(); i++) {
            HtWt item = items.get(i);
            if (i == 0 || items.get(i-1).isBefore(item)) {
                seq.add(item);
            } else {
                firstUnfitItem = i;
            }
          }
      }
      return firstUnfitItem;
    }
    
    
    // Find the maximum length sequence
    void findMaxSeq() {
      Collections.sort(items);
      int currentUnfit = 0;
      while (currentUnfit < items.size()) {
          ArrayList<HtWt> nextSeq = new ArrayList<HtWt>();
          int nextUnfit = fillNextSeq(currentUnfit, nextSeq);
          maxSeq = seqWithMaxLength(maxSeq, nextSeq);
          if (nextUnfit == currentUnfit) 
            break;
          else 
            currentUnfit = nextUnfit;
      }
    }
    

    }

    问题,

    1&GT;函数fillNextSeq的用法是什么? 2 - ;为什么检查“items.get(i-1).isBefore(item)”而不是将当前项目与seq中的最新项目进行比较?

假设排序列表是(1,5),(2,1),(2,2),基于fillNextSeq的功能,

第一个(1,5)将被推入序列中。然后项目(2,1)将不被推入序列b / c(2,1)的权重小于(1,5)。接下来,因为(2,1)在(2,2)之前,所以(2,2)将被推入序列。

现在,序列包含(1,5)和(2,2)不正确b / c(1,5)的权重大于(2,2)的权重。

谢谢

3 个答案:

答案 0 :(得分:2)

fillNextSeq的用法是获取组中增加身高/体重的下一个序列。它通过向ArrayList seq添加连续项来实现此目的,直到遇到更重或更高的人。

items.get(i-1).isBefore(item)的功能是检查下一个人是否比当前人更短更轻。请记住,您已经按身高和体重对人进行了排序,因此,如果下一个人的顺序比当前人更高或更重,那么他们将会排在排序数组中的当前人之前。因此,问题是将当前项目与序列中的最新项目进行比较,它只是通过比较它们在排序数组中的位置来实现。

希望这有帮助,祝你好运!

答案 1 :(得分:0)

我认为我们可以使用动态编程来解决这个问题。这是我的想法:

L(j) -- the largest possible people ending at j ( 0 < j < n)
L(j) = max { L(i) } + 1 where i<j && ht(i)< ht(j) && wt(i)< wt(j)
we're looking for max{L(j)} where 0<j<n.

对于每个j,我们持有一个数组列表。数组列表中人员的ht和wt增加。在处理第j个人时,我们在所有的数组列表上进行二分查找

List<HtWt> F( HtWt[] in, int n){

   ArrayList<HtWt> out = new ArrayList<HtWt>(n);
   out[0].add(int[0]); 

   int maxl = 0, tj = 0;

   for(int j = 1; j < n; j++){

      // choose the longest among all available
      int jl = 0, ti = 0, tp = 0;

      for( i = 0; i < j; i++){

         // find the first greater element in out[i]
         int x = F(out[i], in[j]);

         // find an appropriate position in i to insert j
         if ( x != -1)  
         {
            // compare with the longest list found so far
            if( (out[i].size + 1) > jl ){
              jl = (out[i].size + 1);
              ti = i;
              tp = x;
          }// if             
      }// for i
     out[j] = out[i];
     out[j].add( tp, o[j]);

     if ( out[j].size > maxl){
       maxl = out[j].size
       tj = j;
     } // if
   } // for j

   return out[tj];
 }  // F

 running time: n + nlogn

 For example, (80, 10), (80, 80), (90, 10), (90, 20), (90, 30)
 j = 0, len = 1, out[0] = (80,10) 
 j = 1, len = 1, out[1] = (80,80)
 j = 2, len = 1 , out[2] = (90, 10)
 j = 3, len = 2, out[3] = (80,10)->(90,20)
 j = 4, len = 1, out[4] = (90, 30)

答案 2 :(得分:0)

我在c#中编写了一个解决方案,它有两个部分。

第1部分: - 创建一个比较器,根据身高和体重(身高和体重)按升序排序。

第2部分: - 从末尾对排序后的数组进行线性搜索,使得a [i]应该小于a [i-1]的高度和重量。

下面是代码。我有一些单元测试用例,并检查代码是否正常工作。但有些我觉得这个解决方案中隐藏着一个bug。 请求专家验证代码。

我实现IComparer的Person类

public class Person : IComparer<Person>
{

    public double Height { get; set; }
    public double Weight { get; set; }

    public int Compare(Person p1, Person p2)
    {

        if ((p1.Height > p2.Height) && (p1.Weight > p2.Weight))
            return 1;

        return -1;
    }

}

我的主要方法

public int NumberOfPeople(Person[] p)
    {

        if (p == null || p.Length == 0)
            return -1;

        Array.Sort(p, new Person());
        int last = p.Length - 1;
        int count = 1;
        for (int i = p.Length - 2; i >= 0 ; i--)
        {
            if ((p[i].Height < p[last].Height) && p[i].Weight < p[last].Weight)
            {
                last = i;
                count++;
            }
        }
        return count;
    }

任何形式的帮助都将受到赞赏。