• 回溯法求排列问题


    问题:

    输出n的全排列

    1. 问题描述: 输出自然数1到n的所有不重复的排列,即n的全排列。

    2. 问题分析: 
    (1) 解空间: n的全排列是一组n元一维向量(x1, x2, x3, ... , xn),搜索空间是:1<=xi<=n i=1,2,3,...,n 

    (2) 约束条件: xi互不相同。技巧:采用"数组记录状态信息", 设置n个元素的一维数组d,其中的n个元素用来记录数据1-n的使用情况,已经使用置0,未使用置1

    #include<iostream>
    #include<memory>
    using namespace std;
    int count=0;//解个数
    int n;//输入数据
    int *a ;//解向量
    int *d ;//解状态
    
    void clear( )
    {
        for(int i=1;i<=n+1;i++)
        {
            d[i]=0;
        }
    }
    
    void output()//第0个不存
    {
        for(int i=1;i<=n;i++)
            cout<<a[i]<<ends;
        cout<<endl;
    }
    

    void tryArrangement(int k) { for(int i=1;i<=n;i++) { if(d[i]==0) { a[k]=i; d[i]=1; } else { //表明已用过 continue; } if(k<n) //没搜索到底 { tryArrangement(k+1); } else { count++; output(); } d[a[k]]=0; //回溯 } } int main() { cin>>n; a=new int[n+5];//解向量 d=new int[n+5];//解状态 clear( ); tryArrangement(1); }

    最开始是这样置d[ ]为0的:

    memset(d,0,sizeof(d));

     不行,为什么?

    记住,memset是按字节赋值的,第3个参数指定要赋值的字节的大小,应该改成:

     memset(d,0,sizeof(int)*n);

    算法说明:k为当前处理的第k个元素。上面的复杂度为O(n^n),不是一个好的算法,因此不可能用它去搜索排序树。

    调试分析

    k=1 if(d[1]==0) true a[1]=1; d[1]=1 try(2)
    k=2 if(d[2]==0) a[2]=2 d[2]=1 try(3)
    k=3 if(d[3]==0) a[3]=3; d[3]=1;
    3==n; count=1; output 1 2 3

    d[3]=0;
    } 跳到for( )处运行 F11运行都函数末尾,
    F11又跳到try(3) k=2 d[a[2]]=0
    } 跳到For处运行
    if(d[3]==0) a[2]=3 d[3]=1;
    if(k<3) try(3)

     我的代码:

    void perm(int n,int r)
    {
        int k=1;
        a[k]=0;
        while(k>0)
        {
            a[k]=a[k]+1;
            while(a[k]<=n && !check(k))  
            {
                a[k]++;
            }
            if(a[k]<=n)
            {
                if(k==n)
                {
                    for(int i=1;i<=n;i++)
                        cout<<a[i]<<ends;
                    cout<<endl;
                    count++;
                     
                    
                }
                else
                {
                    k++;
                    a[k]=0;
                }
            }
            else
            {
                a[k]=0;
                k--;
            }
        }
    }

    可以输出全部排列

    另一种解法==也是搜索排列树的算法框架。

    设计:根据全排列的概念,定义数组初始值为(1,2,3,4,。。n),这是全排列的一种结果,然后通过数据间的交换,则可产生所有不同的排列:

    #include<iostream>
    using namespace std;
    
    int a[100],n,s=0;
    
    void output()
    {
        for(int j=1;j<=n;j++)
            cout<<a[j]<<ends;
        cout<<endl;
    }
    
    void  tryArrange(int k)
    {
        int j;
        if(k>n)
        {
            output();
        }
        else
            for(j=k;j<=n;j++)
            {
                swap(k,j);
                tryArrange(k+1);
                swap(k,j); //回溯时,恢复原来的排列
            }
    }
    
    
    int main()
    {
        int i;
        cin>>n;
        for(i=1;i<=n;i++)
            a[i]=i;
        tryArrange(1);
        cout<<"换行符"<<"s="<<s;
    }

    注意c++try是关键字。swap在ios文件中。

  • 相关阅读:
    localhost 和 127.0.0.1 认识
    postgreSQL可视化工具pgAdmin3 导入表结构和数据
    posgreSQL安装失败解决方案
    C#面向对象基本概念总结
    关于数据存储(关系型数据库和非关系型数据库)
    ADO.NET中的五大内置对象
    关于XML
    WPF中TreeView控件SelectedItemChanged方法的MVVM绑定
    WPF中使用MVVM进行multibinding
    WPF中TreeView控件数据绑定和后台动态添加数据(二)
  • 原文地址:https://www.cnblogs.com/youxin/p/2592633.html
Copyright © 2020-2023  润新知