回 帖 发 新 帖 刷新版面

主题:[讨论]排列问题

有N个字符,每个字符用N-1次,然后把这些字符排成一列,怎样排列才能使任意两个字符的相邻次数有且只有两次?首尾两个字符看成相邻。

如3个字符A,B,C排列如下:ABCACB 就能满足上面的要求,3个字符每个用了两次,AB相邻两次(包括首尾),AC相邻两次,BC相邻两次。

问题是如果4个字符ABCD,每个字符用3次,5个字符ABCDE,每个字符用4次,以至于更多的字符,该如何排列呢?

那位高手能编个程序求解吗?

回复列表 (共12个回复)

沙发

这个算法好像非常简单
比如ABCD四个字符
两两任意组合就是 AB AC AD BC BD CD
连起来就是 ABACADBCBDCD
看看符合你的要求不?

板凳

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 楼

1楼的回答不满足相邻次数有且只有两次...
------ 咋不满足呢?

4 楼

[quote]1楼的回答不满足相邻次数有且只有两次...
------ 咋不满足呢?[/quote]
我也不明白,咋不满足呢?2楼能说下不满足的地方么?

5 楼


呵呵,真抱歉...昨晚看错了,对不住.
   您的算法是正确的,而且比我的简单太多。!
我这就修改。。

6 楼

一楼的给出了一种结果,对给定的N,应该有N的阶乘种满足题意的答案。

7 楼

能说具体点吗?谢谢!

8 楼

#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 楼

[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 楼

因为题目要求:任意两个字符的相邻次数有且只有两次,所以就简单了,要是没有这个要求,N!种答案自然不满足,若除掉这个条件楼主用插空思想想一下就知道答案太多了,但你的题目有了上面所诉的要求,所以这个算法就不存在遗漏了。[em2]

我来回复

您尚未登录,请登录后再回复。点此登录或注册