你怎么写一些东西从阵列{1,2,3,...,N-1,N}中选择所有可能的三元组合而不重复?这是来自最近举办的编程竞赛。 N是3的倍数。
使用数组{1,2,3,4,5,6}的示例:
C_1 = { {1,2,3}, {4,5,6} }
C_2 = { {1,2,4}, {3,5,6} }
C_3 = { {1,2,5}, {3,4,6} }
都有效,但
C_bad1 = { {1,2,3}, {3, 4, 5} }
C_bad2 = { {1,2,4}, {3, 5, 6}, {1, 2, 5} }
不是。
答案 0 :(得分:2)
由于N是3的倍数,我们可以使用技巧来解决它:
这应该可以在没有太多花哨工作的情况下为您提供结果。
编辑:我正在等待有人发现上述问题并确实发现了。修复重复的方法是采取额外步骤:步骤3:如果任何三元组按字典顺序排序,则丢弃该组。其他继续。
答案 1 :(得分:2)
你有(N!)/(((3!)^(N / 3))*((N / 3)!))位置(prove)。你可以使用递归算法来提供来自数组{1,2,3,...,N-1,N}的三元组的所有可能组合,而不需要重复。 但是为了产生其中一个,你可以使用任何想法,例如user1952500想法(虽然这个算法也生成(N / 3)!位置重复)或每个,例如你不变的最后 - (N-6) - 成员并在结果开始时将你的解决方案作为前6名成员。(此算法不会产生重复的位置)
递归解决方案:
void combtriples(int begin)
{
for(int i=1;i<=(n/3);i++)
for(int j=1;j<=(n/3);j++)
for(int k=1;k<=(n/3);k++)
{
if ((mark[i]<3) && (mark[j]<3) && (mark[k]<3))
{
count-position++;
c[count][3]=begin;
c[count][4]=begin+1;
c[count][5]=begin+2;
mark[i]++;
mark[j]++;
mark[k]++;
count-member-flase=count-member-flase+3;
if (count-member-flase > 0)
{
combtriples(begin+3);
}
}
}
}
int main()
{
int mark[];
int c[][];
count-position=0;
count-member-flase=0;
combtriples(1);
return 0;
}
答案 2 :(得分:1)
#include <stdio.h>
#define SEL_NUM 3
#define LIST_SIZE 6
void printset(int *list, int *map, int size);
void select(int *list, int *map, int n, int size, int start);
int main(int argc, const char **argv) {
int list[LIST_SIZE] = {1, 2, 3, 4, 5, 6};
int map[LIST_SIZE] = {0};
select(list, map, SEL_NUM, LIST_SIZE, 0);
return 0;
}
void select(int *list, int *map, int n, int size, int start) {
if (n == 0) {
printset(list, map, size);
return;
}
for (int i = start; i < size; i++) {
map[i] = 1;
select(list, map, n - 1, size, i + 1);
map[i] = 0;
}
}
void printset(int *list, int *map, int size) {
int list1[SEL_NUM], list2[SEL_NUM], list1cnt = 0, list2cnt = 0;
for (int i = 0; i < size; i++)
if (map[i])
list1[list1cnt++] = list[i];
else
list2[list2cnt++] = list[i];
for (int i = 0; i < list1cnt; i++)
printf(" %d ", list1[i]);
printf(" -- ");
for (int i = 0; i < list2cnt; i++)
printf(" %d ", list2[i]);
printf("\n");
}
答案 3 :(得分:0)
让我们考虑N有多少这样的不同三元组。首先将T = floor(N / 3)定义为N个元素支持的每组中三元组的数量。然后请注意,由于不需要重复三元组,因此每个三元组中的三元组可以按第一元素递增排序而不失一般性。那么N的三元组总数是:
产品为t:0 - &gt; ((N - 3 * t - 1)*(N - 3 * t - 2)/ 2)的T-1
从这个公式可以直接看到如何构建(强力)算法来生成三元组。
更新:以上仅适用于N%3 == 0.我正在进行概括。强制;见OP的评论
案例:
当你参加编程比赛时,我认为你不需要任何代码。
更新#2: 请注意,要自动消除重复项,必须将每个三元组的第一个元素强制为编号最小的未选择元素。