关闭

一种约束排列的生成算法

911人阅读 评论(0) 收藏 举报

        一种约束排列的生成算法 

                                                                 陈兆斗、柯爱荣

                                                《工程数学学报》

本文所述的约束排列是指: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;
}

0
0

猜你在找
【直播】机器学习&数据挖掘7周实训--韦玮
【套餐】系统集成项目管理工程师顺利通关--徐朋
【直播】3小时掌握Docker最佳实战-徐西宁
【套餐】机器学习系列套餐(算法+实战)--唐宇迪
【直播】计算机视觉原理及实战--屈教授
【套餐】微信订阅号+服务号Java版 v2.0--翟东平
【直播】机器学习之矩阵--黄博士
【套餐】微信订阅号+服务号Java版 v2.0--翟东平
【直播】机器学习之凸优化--马博士
【套餐】Javascript 设计模式实战--曾亮
查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:31533次
    • 积分:438
    • 等级:
    • 排名:千里之外
    • 原创:11篇
    • 转载:9篇
    • 译文:0篇
    • 评论:14条
    文章分类
    最新评论