从 01,02,...,15 这15个数字中任取5个不相同的进行排列,要求将所有满足要求的情况都列出来,写入文本文件,并且尽可能按一定顺序排列。

解决方案 »

  1.   

    看如下一个例子,代码是C++的,并有分析,看懂没问题:通常我们希望检查n 个不同元素的所有排列方式以确定一个最佳的排列。比如,
    a,b 和c 的排列方式有:a b c, a c b, b a c, b c a, cab 和c b a。n 个元素的排列方式共有n !种。
    由于采用非递归的C + +函数来输出n 个元素的所有排列方式很困难,所以可以开发一个递
    归函数来实现。令E= {e1 , ..., en }表示n 个元素的集合,我们的目标是生成该集合的所有排列方
    式。令Ei 为E中移去元素i 以后所获得的集合,perm (X) 表示集合X 中元素的排列方式,ei . p e r m
    (X)表示在perm (X) 中的每个排列方式的前面均加上ei 以后所得到的排列方式。例如,如果
    E= {a, b, c},那么E1= {b, c},perm (E1 ) = ( b c, c b),e1 .perm (E1) = (a b c, a c b)。
    对于递归的基本部分,采用n = 1。当只有一个元素时,只可能产生一种排列方式,所以
    perm (E) = ( e),其中e 是E 中的唯一元素。当n > 1时,perm (E) = e1 .perm (E1 ) +e2 .p e r m
    (E2 ) +e3.perm (E3) + ⋯ +en .perm (En )。这种递归定义形式是采用n 个perm (X) 来定义perm (E), 其
    中每个X 包含n- 1个元素。至此,一个完整的递归定义所需要的基本部分和递归部分都已完成。当n= 3并且E=(a, b, c)时,按照前面的递归定义可得perm (E) =a.perm ( {b, c} ) +b.perm ( {a,
    c} ) +c.perm ( {a, b} )。同样,按照递归定义有perm ( {b, c} ) =b.perm ( {c} ) +c.perm ( {b}), 所以
    a.perm ( {b, c} ) = ab.perm ( {c} ) + ac.perm ( {b}) = a b . c + ac.b = (a b c, a c b)。同理可得
    b.perm ( {a, c}) = ba.perm ( {c}) + bc.perm ( {a}) = b a . c + b c . a = (b a c, b c a),c.perm ( {a, b}) =
    ca.perm ( {b}) + cb.perm ( {a}) = c a . b + c b . a = (c a b, c b a)。所以perm (E) = (a b c, a c b, b a c, b c a,
    c a b, c b a)。
    注意a.perm ( {b, c} )实际上包含两个排列方式:abc 和a c b,a 是它们的前缀,perm ( {b, c} )
    是它们的后缀。同样地,ac.perm ( {b}) 表示前缀为a c、后缀为perm ( {b}) 的排列方式。
    程序1 - 1 0把上述perm (E) 的递归定义转变成一个C++ 函数,这段代码输出所有前缀为l i s t [ 0:
    k-1], 后缀为l i s t [ k:m] 的排列方式。调用Perm(list, 0, n-1) 将得到list[0: n-1] 的所有n! 个排列方
    式,在该调用中,k=0, m= n - 1,因此排列方式的前缀为空,后缀为list[0: n-1] 产生的所有排列
    方式。当k =m 时,仅有一个后缀l i s t [ m ],因此list[0: m] 即是所要产生的输出。当k<m时,先
    用list[k] 与l i s t [ k:m] 中的每个元素进行交换,然后产生list[k+1: m] 的所有排列方式,并用它
    作为list[0: k] 的后缀。S w a p是一个inline 函数,它被用来交换两个变量的值,其定义见程序1 -
    11。P e r m的正确性可用归纳法来证明。
    程序1-10 使用递归函数生成排列
    template<class T>
    void Perm(T list[], int k, int m)
    { / /生成list [k:m ]的所有排列方式
    int i;
    if (k == m) {//输出一个排列方式
    for (i = 0; i <= m; i++)
    cout << list [i];
    cout << endl;
    }
    else // list[k:m ]有多个排列方式
    // 递归地产生这些排列方式
    for (i=k; i <= m; i++) {
    Swap (list[k], list[i]);
    Perm (list, k+1, m);
    Swap (list [k], list [i]);
    }
    }
    程序1 - 11 交换两个值
    template <class T>
    inline void Swap(T& a, T& b)
    {// 交换a和b
    T temp = a; a = b; b = temp;
    }
      

  2.   

    谢谢上面的回复,谁能写一段DELPHI的代码解决上面的问题?高手请进啊!
      

  3.   

    利用集合,很容易的。Delphi2005下通过:不过数据量很大呵,不知有什么用。
    program Test;{$APPTYPE CONSOLE}type
      TSet = Set of 1..200;var
      m, n: Integer;
      d: array [1..200] of Integer;procedure WriteOut;
    var
      i: Integer;
    begin
      for i:=1 to n do
        Write(d[i]:5);
      Writeln;
    end;procedure Search(Index: Integer; s: TSet);
    var
      i: Integer;
    begin
      if Index > n then
      begin
        WriteOut;
        Exit;
      end;  for i := 1 to m do
        if i in s then
        begin
          d[Index] := i;
          Search(Index+1, s - [i]);
        end;
    end;var
      i: Integer;
      s: TSet;
    begin
      Readln(m, n);
      s := [];
      for i := 1 to m do
        s := s + [i];
      Search(1, s);
      Readln;
    end.
      

  4.   

    to QuickKeyBoard: 
    你好,我是这样想的,正好15个数,可不可以用16进制来解决
    15选5最小不重复的是 
    十六进制      十进制   
    12345  对应   74565     
    最大是
    FEDCB  对应   1043915从74565开始,循环加1直到1043915,判断里面如果有重复的数字就去掉,如74566、745BB
    如果没有重复数字,则将每一位16进制数转换成10进制,如7B56A 换成 07 11 05 06 10最后在文本文件中输出如下结果:
    01 02 03 04 05
    01 02 03 04 06
    ...
    15 14 13 12 11帮我再写一下上面的代码好吗,谢谢,另你楼上写的代码里面有数组,还有递归,有些难,不好看懂。
    拜托再帮我写一下!
      

  5.   

    http://community.csdn.net/Expert/topic/3124/3124930.xml?temp=.9141046
      

  6.   

    组合问题的算法:关于组合问题,有n个数,从中取出m个(m<n),不考虑数字的顺序,求一算法将所有的组合输出 
    主要解答者: aiirii 提交人: aiirii 
    感谢:  
    审核者: hthunter 社区对应贴子: 查看 
         A :  我想求这样一个算法:关于组合问题,有n个数,从中取出m个(m<n),不考虑数字的顺序,求一算法将所有的组合输出,谁知道?高分相送  
    ---------------------------------------------------------------  
     
    http://www.cx66.com/cxgzs/program/delphi/267.htm  
     
    Delphi中巧用递归实现组合    
    作者:    评价:    上站日期:  2001-06-29      
    内容说明:      
    来源:      
     
    --------------------------------------------------------------------------------  
     
      在编程的过程中,我们常常要碰到这样一个问题:有n个数,要从其中取出m(m<  =n)个数,列出所有可能的组合。一般来说,使用循环实现,但是逻辑复杂,不容易调试。而使用递归算法,可以大大简化程序。  
      使用递归实现一个算法时,首先要对问题进行降级处理,就是对于处理n的问题,要转化为n-1或者n-2,…..的问题。其次,就是要确定递归结束条件。如果没有递归结束条件,程序就无法结束,导致系统资源消耗殆尽。  
      首先我们分析一下:对1到n所有的整数求和的问题。传统的循环实现程序如下:  
      function  sum(n:integer):integer;  
      var  
       I:integer;  
      Begin  
       Result:=0;  
       For  I:=1  to  n  do  
        Result:=result+I;  
      End;  
      而用递归实现,我们可以得到sum(n)=n+sum(n-1),这就是降级后的结果;如果n=1,那么和肯定为1,不用再进行递归,这就是递归结束的条件。  
      所以这个问题可以用以下递归程序实现:  
      function  sum(n:integer):integer;  
      Begin  
       If  n=1  then  
        Result:=1  
       Else  
        Result:=result+sum(n-1);  
      End;  
     
      下面我们对组合问题进行分析。  
      要从n(假设这n个数为1到n)个数中取出m个数,我们可以先确定是否有第一个数,如果有1,那么从余下的n-1个数中取出m-1个就可以了;而要是没有1,则需要从余下的n-1个数中选出m个数。这样,我们就把问题进行了降级处理,那么什么时候递归结束呢?如果要从若干个数中取出0个,那么说明不需要再进行选取了,认为递归结束;另外一种情况是,要从p个数中选出p个数,这时确定的选法就是这p个数,所以也可以把这p个数作为结果,然后结束递归。这样,我们就确定了组合问题的降级处理和结束条件。  
      我们用过程select来实现组合选数。参数setvailable代表可供选择数的集合,m表示需要从集合setvailable中选取m个元素,setselected表示已经选出来的元素。    
      具体实现如下:  
      procedure  select(setavailable:set  of  1..n,m:integer;setselected:set  of  1..n);  
      begin  
       if  m=0  then  exit;  //不需要选择,结束递归  
       if  CountOfElement(setavailable)=m  then  
       //从m个数中选出m个,那么把setavailable和setselected的并集作为结果,结束递归  
       begin  
        puttoresult(setavailable+setselected);  
        exit  
       end;  
       //到此,如果没有结束,则需要对问题进行降级  
       select(setavailable-[FirstElement(setavailable)],m-1,setselected+[  FirstElement(setavailable)]);  
       //选中集合中的第一个元素,然后从余下的元素中选取m-1个元素  
       select(setavailable-[FirstElement(setavailable)],m,setselected);  
       //若不选择第一个元素,则从余下的元素中选取m个元素  
      end;  
      在上面的程序中,FirstElement从一个集合中取出最小的元素,CountOfElement计算一个集合中的元素个数,puttoresult把得到的组合记录下来,这些函数和过程的实现略去。  
      至此,组合选数的问题就解决了,从以上的程序中,我们可以看出,对于有些问题,用递归来实现非常简单,而且逻辑清晰。
     
      

  7.   

    我用递归写的一个函数
    把k个数按顺序存在NumArray数组里,取R个数的组合(顺序排列)
    function ComData(K:ShortInt;R:shortInt):Boolean;
    var
      i,j:integer;
    begin
       for i:=K downto R do
       begin
          CombArray[R]:=NumArray[i];
          if  R>1 then
             ComData(i-1,R-1)
          else
          begin 
             //输出CombArray数组中的r个数
            for j=1 to r do
               输出CombArray[j]到文本文件     
          end;                                          
       Result:=true;
    end;