我需要在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算法和相关的算法,但我无法想到这一点。
答案 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)
首先按大小的降序排序碎片,这意味着最大的碎片首先出现。现在考虑每个相同部分的序列。
假设我们正在查看大小a
的内容。将所有这些碎片放在塔上。
转到下一个最大尺寸(大小b
,使b < a
),并从此点递归构建所有可能的塔。
塔上至少有一块a
尺寸?如果是,请删除一个尺寸a
并返回步骤2.
以下程序在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;
}