zoukankan      html  css  js  c++  java
  • 回溯法解哈密顿问题

    回溯法求解:

        首先把回路中的所有顶点编号初始化为0,然后,把顶点0当做回路中的第0个顶点,即x0=0;搜索与0邻接的编号最小的顶点,作为它的后续顶点,判断是否满足约束条件,是则到达该顶点,x1取值为满足条件的顶点编号,然后再以同样的方式搜索。

         假设在搜索过程中已经生成了通路L=x0x1....,xi-1,在继续搜索某个顶点作为通路的xi顶点时,
    根据约束条件,在V中选择与xi-1邻接的并且不属于L的编号最小的顶点

      如果搜索成功,则把该顶点作为xi,否则就把L中的xi-1删去(回溯),从xi-1顶点编号加1的位置开始,继续搜索与xi-2相邻接且不属于L的顶点。这个过程一直继续下去。


    当搜索到xn-1时,如果xn-1与x0相邻接,就得到了一天hamilton回路,否则把xi-1删去,继续回溯。
    最后,在回溯过程中,L中只剩下一个顶点x0,表明不存在哈密顿回路。

    #include<iostream>
    #include<cstdio>
     using namespace std;
     
    void hamilton(int **a,int n,int x[])//x[] 存放回路的顶点序号 a不能写成二维数组形式,否则报错:不能从int **转为 int [ ]]
    
    {
        bool *s=new bool[n]; //s记录顶点的使用与否
        for(int i=0;i<n;i++)
        {
            x[i]=-1;
            s[i]=false;
        }
        s[0]=true;
        x[0]=0; //从序号0开始搜索
        int k=1; //初始深度为1,因为有n个节点且第一个节点已给出(k=0),故空间搜索树的深度为n-1(1到n-1)
        while(k>=0) 
        {
            x[k]=x[k]+1;
            while(x[k]<n)
            {
                if((!s[x[k]])&&(a[x[k-1]][x[k]]==1))
                {
                    //顶点x[k]未被使用而起与前一节点x[k-1]有连线
                    break;
                }
    
                else 
                    x[k]=x[k]+1;
                }
            if(x[k]<n)
            {
                if(k!=n-1) //搜索成功,深度加1
                {
                    s[x[k]]=true;
                    k=k+1;
                }
                else
                    break;
            }
            else
            {
                x[k]=-1;
                k=k-1;
                s[x[k]]=false;
            }
        }
    }
     
    
    
    int main()
    {
        int n;
        freopen("货郎担问题42.txt","r",stdin);
        cin>>n;  //顶点数 
        int **a=new int *[n];  
        for(int i=0;i<n;i++)
            a[i]=new int[n];
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                cin>>a[i][j];
        int *x=new int[n];
        hamilton(a,n,x);
        for(int i=0;i<n;i++)
            cout<<x[i]<<ends;
        cout<<endl;
    
    }

    文件如下:

    4
    0 0 1 1
    1 0 1 1
    1 1 0 1

     

    输出0 2 1 3


     

     

     

  • 相关阅读:
    iOS 快语句(block)浅析
    iOS中控制器的创建
    iOS中的截屏
    iOS&UITextView中的placeholder属性
    iOS归档,解档
    iOS内存警告浅析
    scrollWidth,clientWidth,offsetWidth的区别
    css3学习笔记
    页面重构的常用规范
    页面重构的职业定位
  • 原文地址:https://www.cnblogs.com/youxin/p/2588519.html
Copyright © 2011-2022 走看看