每个可能的塔建造的算法

时间:2014-12-04 10:07:11

标签: c algorithm

我需要在C中创建一个程序,该程序应该执行以下操作: 鉴于 n 非零,正数,我打印出所有塔,可以由给定的碎片建造。只有一个规则 - 不能将较大的规则堆叠到较小的规则(但可以堆叠两个相同大小)。所以,如果给我3个数字,1 2 3,可能性是:

3, 2, 1
3, 1
3, 2
3
2, 1
2
1

给出2 2 3,其:

3, 2, 2
3, 2
3
2, 2
2

有人可以帮帮我吗?我试着研究递归算法,进入Tower of Hanoi算法和相关的算法,但我无法想到这一点。

2 个答案:

答案 0 :(得分:2)

根据我的理解,可以通过排序简化问题。如果首先对数字数组进行排序,则问题会减少到输入的所有子数组的输出。如果n表示输入中元素的数量,则会生成2^n个可能的子数组,这些子数组可以递归枚举。

然而,该解决方案要求输入中相同大小的片段被认为是不同的。如果认为相等大小的片段相等,则应对输入进行排序,然后将其转换为(s_i,m_i)对,其中s_i表示i个片段的大小m_i }表示其多样性。然后,可以使用伪代码中的以下算法生成可能的解决方案。

type piece = struct (integer, integer)

function enumerate( a array of piece )
{
    if ( a is empty )
    {
        end current solution
    }
    else
    {
        let f = first element of a
        for each i <= multiplicity of f
        {
            output size of f i times
            enumerate ( a with first element removed )
        }
    }       
}

答案 1 :(得分:1)

首先按大小的降序排序碎片,这意味着最大的碎片首先出现。现在考虑每个相同部分的序列。

  1. 假设我们正在查看大小a的内容。将所有这些碎片放在塔上。

  2. 转到下一个最大尺寸(大小b,使b < a),并从此点递归构建所有可能的塔。

  3. 塔上至少有一块a尺寸?如果是,请删除一个尺寸a并返回步骤2.

  4. 以下程序在ANSI C中实现此算法。用户在命令行中输入部分。我们使用比较函数qsort调用reverse以按降序对输入进行排序,然后调用递归函数print_tower

    #include <stdlib.h>
    #include <stdio.h>
    
    /* Assumes that data is sorted in descending order. */
    void print_tower(int *data, int n, int pos, int *result, int len) {
      int seek, i;
      /* If we're out of data, print the result pieces. */
      if (pos == n) {
        if (len > 0) {
          printf("%d", result[0]);
          for (i = 1; i < len; ++i) {
            printf(", %d", result[i]);
          }
          printf("\n");
        }
        return;
      }
      /* Scan the sequence of identical elements. */
      seek = pos;
      while (seek < n && data[seek] == data[pos]) {
        result[len++] = data[seek++];
      }
      /* Recursively print the tower and shorten the sequence. */
      while (pos++ <= seek) {
        print_tower(data, n, seek, result, len--);
      }
    }
    
    /* Comparison function to sort integers in descending order. */
    int reverse(const void *p, const void *q) {
      int a = *(int *)p, b = *(int *)q;
      return b - a;
    }
    
    int main(int argc, char **args) {
      int i, n = argc-1,
          *data = (int *) malloc(n*sizeof(int)),
          *result = (int *) malloc(n*sizeof(int));
      for (i = 0; i < n; ++i) {
        data[i] = atoi(args[i+1]);
      }
      qsort(data, n, sizeof(int), reverse);
      print_tower(data, n, 0, result, 0);
      return 0;
    }