排列数问题

/*
    Name: 排列数问题 
    Copyright: 
    Author:  巧若拙 
    Date: 15/12/18 13:25
    Description: 排列数问题 
设有n个整数的集合{1,2,3,。。。,n},从中任意取出r个数进行排列(r<=n),试列举所有的排列。
算法分析:从n个数中选取m(m<=n)个数按照一定的顺序进行排成一个列,叫作从n个元素中取m个元素的一个排列。
由排列的定义,显然不同的顺序是一个不同的排列。从n个元素中取m个元素的所有排列的个数,称为排列数。
从n个元素取出n个元素的一个排列,称为一个全排列。全排列的排列数公式为n!,通过乘法原理可以得到。
算法0:回溯算法框架1:先处理递归出口(即终点),再枚举各种可能值,递归搜索下一层。调用函数直接判断是否满足条件,这样无需记录和恢复标记值。     
算法1:回溯算法框架1:以空间换时间,定义数组b用来设置标记,再搜索下一层前后记录和恢复标记值。 
算法2:回溯算法框架2:先枚举各种可能值,再判断是否到达终点,若到达终点则输出结果,否则递归搜索下一层。 
算法2的搜索深度比算法1要少一层,但是不如算法1结构清晰。
算法3:非递归算法:自定义栈模拟算法2的递归过程,注意最后一个位置要单独恢复b[a[t]] = 0。
*/
#include<iostream>
#include<cmath>

using namespace std;

const int N = 10; //整数个数
int a[N+1];
int b[N+1];//当前数字是否被用过
int s = 0;
int n, r;

bool IsOk(int t, int key); //判断key的值是否已经出现过 
void Print();
void dfs(int t); //框架1 
void dfs1(int t); //框架2 
void dfs2(int t); //框架2 
void dfs3(); //非递归算法 

int main()
{
    cin >> n >> r;

//    dfs(1);
//    dfs1(1);
//    dfs2(1);
    dfs3();
    
    return 0;
}

void Print()
{
    cout << ++s << ": ";
    for (int i=1; i<=r; i++)
    {
        cout << a[i] << " ";
    }
    cout << endl; 
}

bool IsOk(int t, int key) //判断key的值是否已经出现过 
{
    for (int i=1; i<t; i++)
    {
        if (a[i] == key)
            return false;
    }
    return true;

void dfs(int t) //框架1,不记录标记,直接判断 
{
    if (t == r+1) //到达终点,输出结果 
    {
        Print(); 
    }
    else
    {
        for (int i=1; i<=n; i++) //枚举各种可能值 
        {
            if (IsOk(t, i)) //满足条件 
            {
                a[t] = i;
                dfs(t+1); //搜索下一层 
            }
        }
    }
}

void dfs1(int t) //框架1,记录标记,以空间换时间 
{
    if (t == r+1) //到达终点,输出结果 
    {
        Print(); 
    }
    else
    {
        for (int i=1; i<=n; i++) //枚举各种可能值 
        {
            if (b[i] == 0) //满足条件 
            {
                a[t] = i;
                b[i] = 1; //修改标记 
                dfs1(t+1); //搜索下一层 
                b[i] = 0; //恢复标记 
            }
        }
    }
}

void dfs2(int t) //框架2 ,记录标记,以空间换时间  
{
    for (int i=1; i<=n; i++) //枚举各种可能值 
    {
        if (b[i] == 0) //满足条件 
        {
            a[t] = i;
            b[i] = 1;  //修改标记 
            if (t == r) //到达终点,输出结果 
            {
                Print(); 
            }
            else
                dfs2(t+1); //搜索下一层 
            b[i] = 0;   //恢复标记 
        }
    }
}

void dfs3() //非递归算法 
{
    int t = 1;
    while (t >= 1)
    {
        while (++a[t] <= n) //枚举各种可能值,a[t]初始化为0 
        {
            if (b[a[t]] == 0)  //满足条件 
            {
                b[a[t]] = 1;  //修改标记  
                if (t == r)  //到达终点,输出结果 
                {
                    b[a[t]] = 0;  //恢复标记 
                    Print(); 
                }
                else
                    t++;  //搜索下一层 
            }
        }
        a[t--] = 0; //回溯 
        b[a[t]] = 0; //恢复标记 
    }
}


 

猜你喜欢

转载自blog.csdn.net/QiaoRuoZhuo/article/details/85013687