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

    假设图中有n个顶点1,2,3,4,5,6,7

    用x[i] 存储问题的解。

    x[1]存储初始点,x[2]存储第二个点。以此类推。

    bool b[n+1][n+1] 存储图的邻接矩阵。

    约束条件:

    xi!=xj          0<=i,j<=n i不等于j

     b[xi-1][xi]=true 当前点与前一个点邻接

    特别地,当i=n时还要满足b[1][n]=true;

    代码:

    #include <iostream>   
    #include<cstdio>
    using namespace std;  
    bool b[100][100]; //图的邻接矩阵 
    
    bool check(int x[],int n, int k)
    {
        
        for(int i=1;i<k;i++)
        {
            if(x[i]==x[k] )
                return false;
        }
        int tmp1,tmp2;
        tmp1=x[k-1],tmp2=x[k];
        if(b[tmp1][tmp2]) //if(b[k-1][k])错误
        {
            if(k==n)
                return b[1][tmp2]; //k等于n要单独考虑
    
            return true;
        }
        else
            return false;
    }
    
    
    void hamilton(int x[],int n,int k)
    {
        for(int i=1;i<=n;i++)
        {
            x[k]=i;
            if(check(x,n,k))
            {
                if(k==n)
                {
                    for(int m=1;m<=n;m++) cout<<x[m]<<ends;
                    cout<<endl;
                     
                }
                else
                {
                    hamilton(x,n,k+1);
                }
            }
        }
    }
    void hamilton2(int x[],int n)
    {
        x[2]=0;
        int k=2;
        while(k>1)
        {
            x[k]+=1;
            while(x[k]<=n && !check(x,n,k) )
            {
                x[k]+=1;
            }
            if(x[k]<=n)
            {
                if(k==n)
                {
                    for(int m=1;m<=n;m++) cout<<x[m]<<ends;
                    cout<<endl;
                    x[k]=0;
                    k--;
                }
                else
                {
                    k++;
                    x[k]=0;
                }
            }
            else
            {
                x[k]=0;
                k--;
            }
        }
    }
     
    int main()
    {
        freopen("hamilton.txt","r",stdin);
        int n;
        cout<<"输入顶点数"<<endl;
        cin>>n;
    
        int *x=new int[n+1];
    
        int edges;
        cout<<"边数"<<endl;
        cin>>edges;
    
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                {
                    if(i==j) b[i][j]=true;
                    else b[i][j]=false;
            }
    
        int start,end;
        cout<<"属于边d的起点和终点"<<endl;
        for(int i=1;i<=edges;i++)
        {
            cin>>start>>end;
    
            b[start][end]=true;
            b[end][start]=true;
        }
        x[1]=1;
        //hamilton(x,n,2);
        hamilton2(x,n);
    }
             

    用递归和不用递归结果都一样。

    注意划红线 部分;

    int k=2;
        while(k>1)
    为什么k>1。
    第一个点x[1]=1;已经确认了,我们从第二个点开始。
    这跟k=1; k>0是一样的道理

    输入:

    5

    8

    1 2 
    1 4
    2 4
    2 3
    4 5
    3 5
    3 4
    2 5


    输出:

    上面代码中的第一个点默认x[1]=1;就是说我们已经规定了起点,如果我们不规定起点,找出所有的哈密顿回路,怎么办?

    调用之前不用写x[1]=1。

    把:

        x[2]=0;
        int k=2;
        while(k>1)
        {
            x[k]+=1;

    改为

        x[1]=0;
        int k=1;
        while(k>0)
        {
            x[k]+=1;

    就可以了吗?不可以,运行就报错。

    原因是什么,是我们的check函数:

    bool check2(int x[],int n, int k)
    {
    
        for(int i=1;i<k;i++)
        {
            if(x[i]==x[k] )
                return false;
        }
        int tmp1,tmp2;
        tmp1=x[k-1],tmp2=x[k];
        if(b[tmp1][tmp2]) //if(b[k-1][k])错误
        {

    当k=1时x[0]是一个随机的数,我们没有赋值。这样b[tmp1][tmp2]必然有问题,我们只要加上k是否为1的判断就可以了。

    在函数最前面加上;

    if(k==1) return true;、

    就可以。

    输出;

  • 相关阅读:
    JNI_Android项目中调用.so动态库实现详解
    Android动态加载so文件
    Android多媒体开发(3)————使用Android NKD编译havlenapetr-FFMpeg-7c27aa2
    Android的NDK开发(5)————Android JNI层实现文件的read、write与seek操作
    Android的NDK开发(4)————JNI数据结构之JNINativeMethod
    Android的NDK开发(3)————JNI数据类型的详解
    ORACLE 实验二
    ORA-12705: Cannot access NLS data files or invalid environment specified
    内存对齐的规则以及作用
    13.怎样自学Struts2之Struts2本地化[视频]
  • 原文地址:https://www.cnblogs.com/youxin/p/3272659.html
Copyright © 2011-2022 走看看