求排列組合的算法


偶需要列舉M個數中n個數的排列 組合。記得窮舉法可以實現,但是麻煩,所以求一個好算法。

11 个解决方案

#1


清華盧開澄的《組合數學》有詳細講解。

我也記不太清了,先看看書再說

#2


先看看這個http://expert.csdn.net/Expert/FAQ/FAQ_Index.asp?id=2987

#3


http://www3.sympatico.ca/qingzhehuang/Generator1.htm

我寫過的一個發生類,不過當時只能計算n個對象的全排列,以及n個數德從0到n個元素的組合。

#4


寫一個苯一點的辦法,無論是排列還是組合都可以按照定義進行
對於排列,從M當中選擇N個,只要其中沒有相同的內容的元素就可以了。
對於組合,其實可以從排列當中提取出來,只輸出升序或者降序的排列就得到了組合。

定義一個N長的數組      int  ctrl[N+1];   初始化每個元素都是1
把ctrl當作一個長度是N的M進制的數字,寫個循環,不斷對它做加一運算
bool AddOne()
{
    for (int i=0; i<N+!; i++ )  {
        ctrl[i]++;          // 直接加一
        if (ctrl[i]==M+1) {
          ctrl[i]=1;  // 模擬進位呢
        }
        else break;   
    };
    if (ctrl[N]>1 ) return false;  // 溢出
    return true;
};


在主程序當中寫一個循環
while ()
{
   判斷ctrl[i]當中的元素的數值
   對於排列的情形,如果各不相同,則是一種排列結果,否則不是 。
   對於組合的情形,如果是升序/降序則是一種組合結果,否則不是。
   if (AddOne()==false) break;
}

#5


組合(用二進制數來指示是否選取):

#include "stdlib.h"
#include "stdio.h"
#include "iostream.h"
#include "math.h"


int binary[100000]={0};

int int_to_binary(int i)  //return the lenth of the binary lenth

int k=0;

while((i!=0)&&(i!=1))
{
binary[k]=i%2;
k++;
i=i/2;
}
    
binary[k]=i;

return k+1;

  

int input[1000];  //sets to be chosen from here





int main(int argc, char* argv[])
{
    int i=0;
int set_lenth=0;
int b_lenth=0;
int num=0;
int j=0;

 
    cout<<"the lenth of the array:";
cin>>set_lenth;

for(i=0;i<set_lenth;i++)
cin>>input[i];

    num=pow(2,set_lenth)-1;

    for(i=1;i<=num;i++)
{
b_lenth=int_to_binary(i);

for(j=0;j<b_lenth;j++)
{
if(binary[j]==1) { cout<<input[j];}
}
    cout<<endl;
}






return 0;
}

#6


列舉所有排列,不用窮舉用什么。

#7


按照《計算機算法設計與分析》上的遞歸算法寫了一個N個數全排列,你將程序改一下就可以了!
package CombinationMath;
 
 public class  Permutation
 {
  private int N;
  private int Data[];
  String str=new String();
 
  public  Permutation(int n)
  {
  if(n<1)
  N=1;
  else
      N=n;
      
  Data=new int[N];
  for(int i=1; i<=N ;i++)
      Data[i-1]=i;
      str+="1到"+N+"的全排列如下:\n";
    }
    
    private void swap(int a,int b)
    {
     int temp;
     temp=Data[a];
     Data[a]=Data[b];
     Data[b]=temp;
    }
    
    /*用遞歸算法實現
     *
     *每次將序列中所有元素交換到開始位置,調用剩下子序列算法
     */
    
    private void RecursiveCreate(int k)
    {
     if(k>=N-1)
     {
     for(int i=0;i<N ;i++)
          str+=Data[i]+" ";
     str+="\n";
        }
        else
        {
         for(int i=k; i<N; i++)
         {
         swap(i,k);
         RecursiveCreate(k+1);
         swap(i,k);
            }
        }
    }
        
    public String toString()
    {
     RecursiveCreate(0);
     return str;
    }
    
}

#8


mark

#9


遞歸比列舉更慢吧

#10


up

#11


遞歸對於大的N不適合,很容易造成棧溢出。
窮舉雖然慢但是因為直接輸出數據,可以避免大內存的開銷。

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com