主题:[讨论]排列问题
jstzhurj
[专家分:4680] 发布于 2010-07-27 15:59:00
有N个字符,每个字符用N-1次,然后把这些字符排成一列,怎样排列才能使任意两个字符的相邻次数有且只有两次?首尾两个字符看成相邻。
如3个字符A,B,C排列如下:ABCACB 就能满足上面的要求,3个字符每个用了两次,AB相邻两次(包括首尾),AC相邻两次,BC相邻两次。
问题是如果4个字符ABCD,每个字符用3次,5个字符ABCDE,每个字符用4次,以至于更多的字符,该如何排列呢?
那位高手能编个程序求解吗?
回复列表 (共12个回复)
沙发
bruceteen [专家分:42660] 发布于 2010-07-27 18:18:00
这个算法好像非常简单
比如ABCD四个字符
两两任意组合就是 AB AC AD BC BD CD
连起来就是 ABACADBCBDCD
看看符合你的要求不?
板凳
dian_ [专家分:50] 发布于 2010-07-28 01:40:00
1楼的算法很简单,也很好...是正确的
(在此对开始的帖子道歉。。)
呵呵,以下附上我的算法————很复杂:
对于四个字符我的答案是:
ABCDACADBDCB
五个字符答案是:
ABCDEACADAEBDBECEDCB
.....
以此类推:
若有N个字符,每个字符用N-1次,则共有(N—1)*N个字符需排..
第一步:N个字符,先顺序排N个;——————————已排N个
第二步:然后以第一个开始,跳过第二个,和第三,第四...第N个排,这样用掉(N-2)*2个字符;
第三步:从第二个开始,依照第二步,即循环第二步...直到倒数第二个停止,即循环到第N-1个数开始时跳出循环;——————————第二三步共排(N-2)*2+(N-3)*2+···+2*2+1*2=(N-2)*(N-1)个字符
第四步:除去首尾两个字符,逆顺序排第2个字符到第N-1个字符;——排N-2个字符
(注:从第一步开始,四步操作产生的字符列顺序链接)
此时共排:N+(N-2)*(N-1)+N-2=N*N-N=N*(N-1)个字符
已排完,且满足排列要求.
(代码略..)
3 楼
bruceteen [专家分:42660] 发布于 2010-07-28 13:01:00
1楼的回答不满足相邻次数有且只有两次...
------ 咋不满足呢?
4 楼
windy0will [专家分:2300] 发布于 2010-07-28 20:59:00
[quote]1楼的回答不满足相邻次数有且只有两次...
------ 咋不满足呢?[/quote]
我也不明白,咋不满足呢?2楼能说下不满足的地方么?
5 楼
dian_ [专家分:50] 发布于 2010-07-28 22:14:00
呵呵,真抱歉...昨晚看错了,对不住.
您的算法是正确的,而且比我的简单太多。!
我这就修改。。
6 楼
k348184904 [专家分:70] 发布于 2010-07-29 02:21:00
一楼的给出了一种结果,对给定的N,应该有N的阶乘种满足题意的答案。
7 楼
jstzhurj [专家分:4680] 发布于 2010-07-29 10:17:00
能说具体点吗?谢谢!
8 楼
k348184904 [专家分:70] 发布于 2010-07-30 15:09:00
#include<stdio.h>
void main()
{
char a[4]={'a','b','c','d'};
int d=0;
char b[24][4];
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
for(int k=0;k<4;k++)
for(int m=0;i!=j&&i!=k&&j!=k&&m<4;m++)
if(m!=i&&m!=j&&m!=k)
{
b[d][0]=a[i];
b[d][1]=a[j];
b[d][2]=a[k];
b[d][3]=a[m];
d++;
}
for(int f=0;f<24;f++)
{
for(int p=0;p<4;p++)
for(int q=p+1;q<4;q++)
printf("%c%c",b[f][p],b[f][q]);
printf("\n");
}
}//四个字母的情况。5个甚至更多,自己改下代码就行了
9 楼
jstzhurj [专家分:4680] 发布于 2010-07-30 16:51:00
[quote]#include<stdio.h>
void main()
{
char a[4]={'a','b','c','d'};
int d=0;
char b[24][4];
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
for(int k=0;k<4;k++)
for(int m=0;i!=j&&i!=k&&j!=k&&m<4;m++)
if(m!=i&&m!=j&&m!=k)
{
b[d][0]=a[i];
b[d][1]=a[j];
b[d][2]=a[k];
b[d][3]=a[m];
d++;
}
for(int f=0;f<24;f++)
{
for(int p=0;p<4;p++)
for(int q=p+1;q<4;q++)
printf("%c%c",b[f][p],b[f][q]);
printf("\n");
}
}//四个字母的情况。5个甚至更多,自己改下代码就行了[/quote]
意思是先对字符进行一次全排列,有N!种排列方式,然后两两组合?除此之外,是否还有遗漏的方式呢?
10 楼
k348184904 [专家分:70] 发布于 2010-07-30 21:15:00
因为题目要求:任意两个字符的相邻次数有且只有两次,所以就简单了,要是没有这个要求,N!种答案自然不满足,若除掉这个条件楼主用插空思想想一下就知道答案太多了,但你的题目有了上面所诉的要求,所以这个算法就不存在遗漏了。[em2]
我来回复