zoukankan      html  css  js  c++  java
  • 【暴力】枚举生成全排列

    (刘汝佳紫皮书)

    生成1~n的排列。

    对于一个长度为n数组长度的数组={0,1,2,3,..., n-1}。要想枚举它的所有的长度为n的全排列出来。

    有两种选择:一个是直接枚举, 另外一个是使用递归来构造。

    1.直接枚举

    n 大的时候就要写 n-1个for循环

    2.递归

    递归函数: print_permutation(int n, int *A, int cur)

    递归使用需要有判定界限,定义一个数组A,往A[]里面放我们需要排列的元素。 cur为当前要确定的元素位置。我们的判定界限则是: 当 n=cur 时 return 。 

    代码如下。

     1 void print_permutation(int n, int* A, int cur)
     2 {
     3     if(n == cur)//排列到n个长度后输出
     4     {
     5         for(int i = 0; i < n; i++)
     6             cout << A[i];
     7         cout << endl;
     8         return;
     9     }
    10     else
    11     {
    12         for(int i = 0; i < n; i++)
    13         {
    14             int ok = 1;
    15             for(int j = 0; j < cur; j++)
    16             //判断i是不是已经使用过了
    17                 if(A[j] == i)
    18                     ok = 0;
    19             if(ok)
    20             {
    21                 A[cur] = i;
    22                 print_permutation(n, A, cur + 1);
    23             }
    24         }
    25     }
    26 }

    生成可重集的排列

    详细描述见刘汝佳紫皮书185页。

    因为重集,所以只需要在上面代码上加重集元素出现次数的比较即可。

     1 #include <iostream>  
     2 #include <algorithm>  
     3 using namespace std;  
     4 
     5 void printPermutation(int n, int* p, int cur, int* arr)        //n是元素个数,p是初始元素集合,cur是当前位置,arr是目前已经排列的部分
     6 {
     7     int i, j;
     8     if (cur == n)
     9     {
    10         for (i = 0; i < n; i++)
    11         {
    12             printf("%d ", arr[i]);
    13         }
    14         printf("
    ");
    15     }
    16     else
    17     {
    18         for (i = 0; i < n; i++)
    19         {
    20             if (i == 0 || p[i] != p[i-1])    //只需要检查第一个元素,以及与前一个元素不相同的元素即可,保证不重复
    21             {
    22                 int c1 = 0, c2 = 0;
    23                 for (j = 0; j < cur; j++)    //已经排列的元素中p[i]出现的次数
    24                 {
    25                     if (arr[j] == p[i])
    26                     {
    27                         c1++;
    28                     }
    29                 }
    30                 for (j = 0; j < n; j++)        //全部元素中p[i]出现的次数
    31                 {
    32                     if (p[i] == p[j])
    33                     {
    34                         c2++;
    35                     }
    36                 }
    37                 if (c1 < c2)    //保证不遗漏
    38                 {
    39                     arr[cur] = p[i];
    40                     printPermutation(n, p, cur+1, arr);
    41                 }
    42             }
    43         }
    44     }
    45 }
    46 
    47 int main()  
    48 {  
    49     int p[5] = {4, 1, 1, 4, 1};
    50     sort(p, p+5);    //排序
    51     int arr[5] = {0};
    52     printPermutation(5, p, 0, arr);
    53     return 0;
    54 }  
  • 相关阅读:
    linux初始密码Mysql
    lamp整个打包
    模拟小球碰撞后返回
    Linux图形界面卡死
    非模态对话框
    菜单
    键盘消息简单示例
    菜单练习
    模态对话框练习
    阶段知识整合(画笔,画刷,字体)
  • 原文地址:https://www.cnblogs.com/Kohinur/p/8523856.html
Copyright © 2011-2022 走看看