一种约束排列的生成算法

转载 2007年10月04日 17:53:00

        一种约束排列的生成算法 

                                                                 陈兆斗、柯爱荣

                                                《工程数学学报》

本文所述的约束排列是指:m个非负整数所构成的排列a1a2...am,满足约束条件:a1<=N1,a2<=N2,...,am<=Nm及a1+a2+...+am=M,其中M和N1,N2...  ,Nm是给定的正整数。

算法描述:

算法设计的主要思想来源于p进制整数的进位方法。所不同的是各个位上的进制不同,并有约束条件a1+a2+...+am=M。将上述所有的约束排列记为( |N1,N2...  ,Nm|;M )。其中按照字典排序法,最大排列记为max{ |N1,N2...  ,Nm|;M },最小排列记为min{ |N1,N2...  ,Nm|;M}。下面的数据表是一个具体的约束排列(|3 4 2 3|;9}的所有结果,它们是按字典排序法依照升序给出的。其中最后一列是按照各个排列的次序由小到大所给出的标号:

0  4  2  3                            1
1  3  2  3                            2   
1  4  1  3                            3
1  4  2  2                            4
2  2  2  3                            5
2  3  1  3                            6
2  3  2  2                            7
2  4  0  3                            8
2  4  1  2                            9
2  4  2  1                           10
3  1  2  3                           11
3  2  1  3                           12
3  2  2  2                           13
3  3  0  3                           14
3  3  1  2                           15
3  3  2  1                           16
3  4  0  2                           17
3  4  1  1                           18
3  4  2  0                           19

显然,表中的最大排列为第19号排列3420;最小排列为第1号排列0423。我们对算法的要求是输入其中的任何一个排列,算法按字典排序法自动生成下一个排列,例如:输入第7号排列2322,则应输出第8号排列2403,算法分为以下几个步骤:

1):输入排列a1a2...am,并检验该排列是否满足约束要求。

2):从排列a1a2...am最右边的个位向左依次判断ajaj+1...am是否为约束排列( |Nj,Nj+1...  ,Nm|;Mj ),其中Mj=M-(a1+a2+...+aj-1),j=m,m-1,...,2,1。

3):在上述依次取j=m,m-1,...,2,1的过程中,设k为上述过程中第一个不是约束排列( |Nk,Nk+1...  ,Nm|;Mk )的最大排列的位。即akak+1...am不是( |Nk,Nk+1...  ,Nm|;Mk )的最大排列,而对于i=k+1,k+2,...  ,m,aiai+1...am都是( |Ni,Ni+1...  ,Nm|;Mi )的最大排列。

4):如果k=0则终止。否则,将ak改为ak`=ak+1,取排列ak+1`ak+2`...am`=min{ |Nk+1,Nk+2...  ,Nm|;Mk`},其中Mk`=M-(a1+a2+...+ak-1+ak`)。

5):生成的下一个排列就是:a1a2...akak`ak+1`ak+2`...am`

可以看到在此算法中,最大、最小排列起到重要作用,因为它们的算法都比较简单,在本文中从略。

附:C++实现代码:

 

#include <cstdlib>
#include 
<iostream>

using namespace std;

const int n=4;
int   restraint[n+1]=...{3,4,2,3,9};
int   list[n];

bool  Is_Max_Permutation( int index )...{//index : 头位置, 0表示开始于list[0] 
      int  i, sum=restraint[n];
      
for( i=0; i<index; ++i )
           sum
-=list[i];
      i
=n-1;
      
while( i>=index )...{
             
int  j, temp=0, mid;
             
for( j=index; j<i; ++j )
                  temp
+=restraint[j];
             temp
=sum-temp;
             mid
=temp>0? temp : 0;
             
if( mid!=list[i] )
                 
return false;
             sum
-=mid;
             
--i;
      }

      
return true;
}


void  Get_Min_Permutation( int index )...{//index : 头位置, 0表示开始于list[0]
      int  i, sum=restraint[n];
      
for( i=0; i<index; ++i )
           sum
-=list[i];
      i
=index;
      
while( i<=n-1 )...{
             
int j, temp=0;
             
for( j=n-1; j>i; --j )
                  temp
+=restraint[j];
             temp
=sum-temp;
             list[i]
=temp>0? temp : 0;
             sum
-=list[i];
             
++i;
      }

}
    

bool  Next_Permutation( )...{
      
int  i=n-1;
      
while( Is_Max_Permutation( i ) && i>=0 )
             
--i;
      
if( i<0 )
          
return false;
      list[i]
++;
      Get_Min_Permutation( i
+1 );
      
return true;
}

                    
int main(int argc, char *argv[])
...
    Get_Min_Permutation( 
0 );
    
int  i;
    
do
    
...{
      
for( i=0; i<n; ++i )
           cout
<<list[i]<<"  ";
      cout
<<endl;
    }
while( Next_Permutation( ) );
    system(
"PAUSE");
    
return EXIT_SUCCESS;
}

全排列生成算法(二)

Steinhaus-Johnson-Trotter算法是一种基于最小变换的全排列生成算法,对于排列a[1...n],该算法通过将a[i],与a[i-1](或a[i+1])进行交换,生成下一个排列,直到...
  • joylnwang
  • joylnwang
  • 2011年12月15日 14:34
  • 4799

算法--生成1~n的排列

在暴力求解法中,我们常常要用上枚举一些简单内容以便方便获得解,若要输出整数n的前n个整数的全排列,则按字典序输出为: (1,2,3),(1,3,2),(2,1,3),(2,3,1),(3,1,2),(...
  • hhhzua
  • hhhzua
  • 2015年04月05日 19:54
  • 778

排列生成算法--字典序法

本文地址: 所谓字典序法就是按照字典排序的思想逐一产生所有排列。比如1,2,3,4四个数字进行全排列,先1234, 1243,1324,1342,1423,1432,…4321。 由1243生成132...
  • spch2008
  • spch2008
  • 2013年07月30日 21:24
  • 1271

Johnson_Trotter 生成排列算法

const int N = 10; int f[N],d[N]; void init(int n) { for(int i=1; i
  • acm_BaiHuzi
  • acm_BaiHuzi
  • 2015年10月23日 16:55
  • 708

排列熵算法简介及c#实现

一、   排列熵算法简介: 排列熵算法(Permutation Entroy)为度量时间序列复杂性的一种方法,算法描述如下: 设一维时间序列: 采用相空间重构延迟坐标法对X中任一...
  • zbc1090549839
  • zbc1090549839
  • 2015年06月12日 19:58
  • 3709

全排列的生成算法:字典序法

http://blog.sina.com.cn/s/blog_4cd4ffc401018x7r.html 全排列的生成算法 对于给定的字符集,用有效的方法将所有可能的全排列无重复...
  • kuailexiaoziwqx
  • kuailexiaoziwqx
  • 2016年08月14日 21:00
  • 1271

生成全排列算法详解

递归+回溯+SWAP。字典序
  • Dafang_Xu
  • Dafang_Xu
  • 2015年10月17日 17:20
  • 1979

全排列的算法(八)——序数法

全排列的生成算法(八)——序数法   n个元素的全排列有n!个,如果将排列按顺序编号,并能够按照某种方法建立起每一个序号与一个排列之间的对应关系,那么就可以根据序号确定排列,反过来也可以根据排列确...
  • BabyNumber
  • BabyNumber
  • 2015年03月12日 09:19
  • 1729

Steinhaus-Johnson-Trotter 生成全排列算法

Steinhaus-Johnson-Trotter算法是一种基于最小变换的全排列生成算法,对于排列a[1...n],该算法通过将a[i],与a[i-1](或a[i+1])进行交换,生成下一个排列,直到...
  • kalilili
  • kalilili
  • 2015年01月10日 00:43
  • 1300

生成下一个排列 By ACReaper

生成下一个排列的算法有很多中,用递归来实现是最简单,最明了的。我下面介绍的不是按照递归了实现而是从实际问题分析,总结出的规律。 我们知道对于排列a1a2a3......an,如果aj 怎么判断,...
  • sixleaves
  • sixleaves
  • 2013年04月30日 23:13
  • 835
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:一种约束排列的生成算法
举报原因:
原因补充:

(最多只允许输入30个字)