[pieces] C++全排列 ×3 两份实现,以及喜人的next_permutation()

正解

void permutation(int d, int max_depth)
{
    static bool flag = false, used[15];
    static char cache[15];
    if (d == max_depth)
    { 
        if (flag) cout << ", "; 
        cout << cache;
        flag = true; return; 
    }
    for (int i = 1; i <= max_depth; i++)
        if (!used[i]) 
        { 
            used[i] = true; 
            cache[d] = '0'+i;
            permutation(d+1, max_depth);
            used[i] = false;
        }
}

一个数学大佬的移动方法
虽然数学上很巧妙,但着实对机器很不友好。

int factorial(int n){// 最好只算一次
    if(n==1) return 1;
    else return factorial(n-1)*n;
}
//---------------------------------------------------------------------

//这一段是万恶之源
void change(int ls[],int k,int n){ //change the bit of k and n: k to left.
    int btw;
    for(int i=n;i>=k+1;i--){
        btw = ls[i-1];
        ls[i-1]=ls[i];
        ls[i]=btw;
    }
}
void rchange(int ls[],int k,int n){//recursion: change back the bit of k and n.
    int btw;
    for(int i=k;i<=n-1;i++){
        btw=ls[i+1];
        ls[i+1]=ls[i];
        ls[i]=btw;
    }
}
//---------------------------------------------------------------------
int fact;//只算一次也只减少了3s
void para(int ls[],int k,int n){
    static int num=0;
    if(k==n-1){
        for(int i=0;i<=n-1;i++){
            printf("%d",ls[i]);
        }
        if(num!=fact-1) putchar(',');//这里减少计算之后会少用约3s
        num++;
    }
    else{
        for(int i=k;i<=n-1;i++){
            change(ls,k,i);
            para(ls,k+1,n);
            rchange(ls,k,i);
        }
    }
}
int main(){
    int n = 9;
    // scanf("%d",&n);
    int list[10];
    for(int i=0;i<n;i++){
        list[i]=i+1;
    }
    fact = factorial(n);
    para(list,0,n);
    return 0;
}

运行结果:
在这里插入图片描述
在这里插入图片描述

同时如果调用next_permutation函数,效果着实是惊人的。它竟然和深搜没差多少!

#include <bits/stdc++.h>
using namespace std;
int main()
{
    char cache[10] = {'1','2','3','4','5','6','7','8','9'};
    cout << cache;
    while (next_permutation(cache, cache+9))
        cout << ", " << cache;
    return 0;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值