暴力求解法—排列枚举

本文介绍了如何使用递归和C++标准库函数next_permutation生成整数排列。首先通过递归函数print_permutation生成1到n的所有排列,然后展示了如何在已排序的输入中生成下一个更大的排列,直至达到最大排列。此外,还提到了next_permutation函数的使用,该函数用于输出所有大于当前排列的排列。这些方法在算法和计算机科学中有着广泛应用。
摘要由CSDN通过智能技术生成

生成1~n的排列

#include <iostream>
using namespace std;
void print_permutation(int n, int A[], int cur){
    if(cur == n){
        for(int i=0; i<n; i++)
            printf("%d ",A[i]);
        printf("\n");
    }
    else for(int i=1; i<=n; i++){
        bool ok = true;
        for(int j=0; j<cur; j++)
            if(A[j] == i)
                ok = false;
        if(ok){
            A[cur] = i;
            print_permutation(n, A, cur+1);
            
        }
    }
}
int main(int argc, const char * argv[]) {
    int A[9];
    print_permutation(9, A, 0);
    return 0;
}

生成可重集的排列

#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <cstdio>
#include <algorithm>
using namespace std;
vector<int> P;
void scan(){
    string numbers;
    getline(cin,numbers);
    stringstream ss(numbers);
    char number;
    // 遇到空格则视为下一个循环
    while(ss >> number) P.push_back(number - '0');
}
void print_permutation(vector<int> &P, int A[], int cur){
    if(cur==P.size()){
        for(int i=0;i<cur;i++)
            printf("%d",A[i]);
        printf("\n");
    }
    else for(int i=0;i<P.size();i++) 
    		// 因为要求不输出重复排列,那么对于重复数字来说,
    		// 我们得视为1个,也就是说,每次循环只能出现这些数中的一个
    		// 这样,无论再多也是1x1x1...
	    	if(!i||P[i]!=P[i-1]){
	        int cnt1=0,cnt2=0;
	        // 我们还要保证重复数字出现的数目不能超过其有的数目
	        for(int j=0;j<cur;j++) if(A[j]==P[i]) cnt1++;
	        for(int j=0;j<P.size();j++) if(P[j]==P[i]) cnt2++;
	        if(cnt1<cnt2){
	            A[cur] = P[i];
	            print_permutation(P, A, cur+1);
	        }
    }
}
int main(int argc, const char * argv[]) {
    scan();
    // 在开始前,务必要排序
    sort(P.begin(),P.end());
    const vector<int>::size_type n = P.size();
    int A[n];
    print_permutation(P, A, 0);
    return 0;
}

下一个排列

介绍

bool next_permutation(iterator start, iterator end);
// 输出所有比当前排序大的排列,顺序是从小打大;
// prev_permutation则是相反。

代码

#include <iostream>
#include <algorithm>
using namespace std;
int main(int argc, const char * argv[]) {
    int n,p[10];
    scanf("%d",&n);
    for(int i=0; i<n; i++) scanf("%d", &p[i]);
    sort(p,p+n);
    do{
        for(int i=0; i<n; i++) printf("%d",p[i]);
        printf("\n");
    }while(next_permutation(p, p+n));
    return 0;
}

可以看到,它只生成比当前排列大的一个排列。如果这个排列到头了,返回false。

总结

综上所述,实现枚举排列的方法有两种:

  1. 递归法;
  2. next_permutation.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

右边是我女神

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值