| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 476 人关注过本帖, 1 人收藏
标题:求一段排列代码
只看楼主 加入收藏
djyjysxxs
Rank: 1
等 级:新手上路
帖 子:5
专家分:0
注 册:2013-9-8
结帖率:0
收藏(1)
已结贴  问题点数:20 回复次数:4 
求一段排列代码
有一个100个元素的一维数组,由单个字母随机组成,如:A    A    A    A    A    A    A    A    A    A    B    B    B    B    B    C    C    C    C    C    C    C    C    C    C    C    C    C    D    D    D    D    D    D    D    D    E    E    E    E    E    E    E    E    E    E    E    F    F    F    F    F    F    F    G    G    G    G    G    G    G    G    H    H    H    H    H    H    H    H    H    H    H    I    I    I    I    I    I    I    I    I    I    I    I    I    I    I    I    I    I    I    J    J    J    J    J    J    J    J

仅是示例,实际中字母A、B等的个数是随机的,也许只有两个A没有B。字母的种类也是随机的,也许还有R、S、T或X、Y、Z。
现需要将他们按30个元素一组分组,并将每组写入五列六行的矩阵,如这样的一个:
A    G    H    C    G
B    E    A    D    A
C    G    C    G    B
B    H    E    A    C
A    F    B    G    B
B    C    A    F    A
要求是:
为便于叙述,先将这个矩阵的每个位置进行如下编号:
1    7    13    19    25
2    8    14    20    26
3    9    15    21    27
4    10    16    22    28
5    11    17    23    29
6    12    18    24    30

一、相邻元素不能相同,相邻是指:如与1号相邻的有2、7、8,如与4号相邻的有3、5、9、10、11,如与15号相邻的有8、9、10、14、16、20、21、22,如与29号相邻的有22、23、24、28、30,等等
二、当不足30个元素时,优先填编号小的,空编号大的
求各位赐教一段代码,代码的结果可以只生成另一个排列好的一维数组,我拿来可以依次写入矩阵即可。谢谢!

搜索更多相关主题的帖子: 元素 字母 
2013-09-08 10:53
qunxingw
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:贵宾
威 望:24
帖 子:1676
专家分:7295
注 册:2011-6-30
收藏
得分:10 
写了一个从26个字母里选满足条件形成的A[6][5],
程序代码:
#include<stdio.h>
#include<stdlib.h>
char A[6][5];
char a[]={"abcdefghijklmnopqrstuvwxyz"};
int isok(int n)//分析A[][]当前数与前面的数比较为递归 作准备。 
{
     int k,flat=1;
  
    if(A[n/5][n%5]==A[n/5-1][n%5-1])   flat=0;
    if(A[n/5][n%5]==A[n/5-1][n%5] )    flat=0;
    if(A[n/5][n%5]==A[n/5-1][n%5+1])   flat=0;
    if(A[n/5][n%5]==A[n/5][n%5-1])     flat=0;
  
  
    return flat;
}




void output()
{
     int i,j;
     for(i=0; i<6;i++)
     {
     for(j=0; j<5;j++)
     printf("%2c",A[i][j]);
     printf("\n");
     }
     printf("***********************\n");
}

void ok(int n)
{
      int j;
      if(n==30)
   {
       output();
   return ;
   }
     
    for(j=0;j<26;j++)
      {
      A[n/5][n%5]=a[j];
      if(isok(n) ) ok(n+1);
      }
  }
  
  int main()
  {
      ok(0);
      system("pause");
      return 0;
  }


[ 本帖最后由 qunxingw 于 2013-9-11 15:58 编辑 ]

www.qunxingw.wang
2013-09-10 17:12
风吹过b
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:364
帖 子:4947
专家分:30084
注 册:2008-10-15
收藏
得分:10 
显示控件Label1 排列是
1    7    13    19    25
2    8    14    20    26
3    9    15    21    27
4    10    16    22    28
5    11    17    23    29
6    12    18    24    30

0号控件不使用。

程序代码:
Option Explicit

Private Sub Command1_Click()
Dim a(1 To 30) As Long, b(1 To 30) As Long
Dim c(1 To 30) As Long

Dim i As Long, j As Long
Dim m As Long
Dim k As Boolean

'初始化随机数据发生器
Randomize

'产生30个连续数据
For i = 1 To 30
    a(i) = i
Next i

'排列开始。因有可能需要重排,所以使用 DO 循环
Do
'初始化位置,全置 0
For i = 1 To 30
    b(i) = 0
    Label1(i) = 0       '先显示结果
    DoEvents
Next i

'开始排列,以数据为变化
For i = 1 To 30
    '搜索可能位置
    For j = 1 To 30
        '如果无值
        If b(j) = 0 Then
            k = True                '先置可放入
            '--------8个方向进行搜索,有相邻数据均设置为不可放入---------
            '使用 <= ,可以确保 相同的数据也不会排列到一起去。如, 1-15 ,每样2个,也可以正确排列出来
            If  j > 1 And j Mod 6 > 1 Then                                                       '
                If b(j - 1) > 0 And Abs(b(j - 1) - a(i)) <= 1 Then k = False
            End If
            
            If j Mod 6 > 0 Then                                                         '
                If b(j + 1) > 0 And Abs(b(j + 1) - a(i)) <= 1 Then k = False
            End If
            
            
            If j > 6 And j Mod 6 > 0 Then                                               '左下
                If b(j - 5) > 0 And Abs(b(j - 5) - a(i)) <= 1 Then k = False
            End If
                        
            If j > 6 Then                                                               '
                If b(j - 6) > 0 And Abs(b(j - 6) - a(i)) <= 1 Then k = False
            End If
            
            If j > 6 And j Mod 6 > 1 Then                                               '左上
                If b(j - 7) > 0 And Abs(b(j - 7) - a(i)) <= 1 Then k = False
            End If
            
            If j < 25 And j Mod 6 > 0 Then                                              '右上
                If b(j + 5) > 0 And Abs(b(j + 5) - a(i)) <= 1 Then k = False
            End If
            
            If j < 25 Then                                                              '
                If b(j + 6) > 0 And Abs(b(j + 6) - a(i)) <= 1 Then k = False
            End If
                        
            If j < 25 And j Mod 6 > 1 Then                                              '右下
                If b(j + 7) > 0 And Abs(b(j + 7) - a(i)) <= 1 Then k = False
            End If
        Else
        '对应 如果无值 ,否则设置为不可放入
            k = False
        End If
            '该位置经过 8个位置判断或有值判断后,根据是否可放入,设置位置的的标志。
            If k Then
                c(j) = 1
            Else
                c(j) = 0
            End If
    Next j
    
    '计算可放入 位置总数
    m = 0
    For j = 1 To 30
        m = m + c(j)
    Next j
    '如果可放入位置总数为0 ,表示没有一个位置可以放入,退出 FOR 循环,以便重新开始排列。
    If m = 0 Then
        Exit For
    End If
    
    '产生一个随机位置
    Do
        j = Int(Rnd() * 30 + 1)
    Loop While c(j) = 0             '产生的随机位置是不可以放入数据的位置时,重新去产生随机位置
    b(j) = a(i)                     '得到可以放入数据的随机位置,放入数据
    Label1(j) = b(j)                '同时显示出来
    DoEvents
Next i

Loop While i < 31                   '如果 I=31 时,表示 循环正常结束,也意味着所有的数据都放入,当 I<31时,表示没有正常结束,也就需要重新排列

For i = 1 To 30                     '重新显示一遍结果
    Label1(i).Caption = b(i)
Next i

End Sub



[ 本帖最后由 风吹过b 于 2013-9-11 11:53 编辑 ]

授人于鱼,不如授人于渔
早已停用QQ了
2013-09-11 11:46
djyjysxxs
Rank: 1
等 级:新手上路
帖 子:5
专家分:0
注 册:2013-9-8
收藏
得分:0 
谢谢2楼,但由于不懂C,所以发在VB版块。还是谢谢您!
谢谢版主!您给出的代码非常好、非常详尽!

主要是我不懂如何回溯:比如前20个都排好了,后面的却怎么也不能排下去,如何返回重排第20个甚至第19、18直至第1?前几个30都排好了,剩下的却无法排,如何返回重排前一个30甚至前几个30?
如果不能全部按规则排,给出提示:能排的部份排好展示出来,不能排的部份另给说明也展示出来
再请版主在这方面再给予指教!谢谢!
2013-09-11 16:30
风吹过b
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:364
帖 子:4947
专家分:30084
注 册:2008-10-15
收藏
得分:0 
我不是使用 重排第几个 以达到目的的。
我是 发现排不了,就全部重排 。

我的代码里,如果需要回溯,会很麻烦,需要 冲洗 所需要回溯填好后的数值,然后再重新从那个值继续填充。
因为不知道是因为 哪个数据造成填充失败,所以很多时候不知道需要回溯到哪一个值为止。

-----
    '计算可放入 位置总数
    m = 0
    For j = 1 To 30
        m = m + c(j)
    Next j
    '如果可放入位置总数为0 ,表示没有一个位置可以放入,退出 FOR 循环,以便重新开始排列。
如果要给说明,那么在这里 生成提示说明。 当前数无法填入。
    If m = 0 Then
        Exit For
    End If

。。。。。
Loop While i < 31                   '如果 I=31 时,表示 循环正常结束,也意味着所有的数据都放入,当 I<31时,表示没有正常结束,也就需要重新排列
这里是 重新开始排列的代码。

-------------
当有重复数据时,有可能会导致 相同的数据相邻,原因还没找到。
每个数字都有 3个 相同时,这个错误的概率估计在 5% 左右。
-------------

排列后,你应该自己加一段 验证代码 上去 ,以克服上面的这个错误。

[ 本帖最后由 风吹过b 于 2013-9-11 17:16 编辑 ]

授人于鱼,不如授人于渔
早已停用QQ了
2013-09-11 17:15
快速回复:求一段排列代码
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.032498 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved