C语言使用回溯法解旅行售货员问题与图的m着色问题

 更新时间:2016年07月04日 16:13:24   作者:Hi_Aaron  
回溯法即是在按条件搜索走不通的情况下退回再选择其他路线的方法,这里我们来看C语言使用回溯法解旅行售货员问题与图的m着色问题的方法示例:

旅行售货员问题
1.问题描述:

旅行售货员问题又称TSP问题,问题如下:某售货员要到若干个城市推销商品,已知各城市之间的路程(或旅费),他要选定一条从驻地出发,经过每个城市一遍最后回到驻地的路线,使总的路线(或总的旅费)最小。数学模型为给定一个无向图,求遍历每一个顶点一次且仅一次的一条回路,最后回到起点的最小花费。

2.输入要求:

输入的第一行为测试样例的个数T( T < 120 ),接下来有T个测试样例。每个测试样例的第一行是无向图的顶点数n、边数m( n < 12,m < 100 ),接下来m行,每行三个整数u、v和w,表示顶点u和v之间有一条权值为w的边相连。( 1 <= u < v <= n,w <= 1000 )。假设起点(驻地)为1号顶点。

3.输出要求:

对应每个测试样例输出一行,格式为"Case #: W",其中'#'表示第几个测试样例(从1开始计),W为TSP问题的最优解,如果找不到可行方案则输出-1。

4.样例输入:

2
5 8
1 2 5
1 4 7
1 5 9
2 3 10
2 4 3
2 5 6
3 4 8
4 5 4
3 1
1 2 10

5.样例输出:

Case 1: 36
Case 2: -1

6.解决方法:

//旅行售货员问题 (回溯)
#include<iostream> 
#define N 100 
using namespace std; 
int n,m,w,      //图的顶点数和边数
  graph[N][N],   //图的加权邻接矩阵
  c=0,       //当前费用
  bestc=-1,     //当前最优值
  x[N],      //当前解
  bestx[N];    //当前最优解
void backtrack(int k); 
void swap(int &a,int &b); 
void swap(int &a,int &b) 
{ 
  int temp=a; 
  a=b; 
  b=temp; 
} 
void backtrack(int k) 
{ 
  if(k==n) 
  { 
    if( (c+graph[x[n-1]][x[n]]+graph[x[n]][1]<bestc||bestc==-1) && graph[x[n-1]][x[n]]!=-1 && graph[x[n]][1]!=-1 ) 
    { 
      bestc=c+graph[x[n-1]][x[n]]+graph[x[n]][1]; 
      for(int i=1;i<=n;i++) 
      { 
        bestx[i]=x[i]; 
      } 
    } 
    return ; 
  } 
  else 
  { 
    for(int i=k;i<=n;i++) 
    { 
      if( graph[x[k-1]][x[i]]!=-1 && (c+graph[x[k-1]][x[i]]<bestc || bestc==-1)) 
      { 
        swap(x[i],x[k]); 
        c+=graph[x[k-1]][x[k]]; 
        backtrack(k+1); 
        c-=graph[x[k-1]][x[k]]; 
        swap(x[i],x[k]); 
      } 
    } 
  } 
} 


int main(void)
{
  int i,j,tmp=1,testNum;
  cin>>testNum;
  while(tmp<=testNum)
  {
    cin>>n>>m;
    for(i=1;i<=n;i++)
    for(j=1;j<=n;j++)
    graph[i][j]=-1;
    for(int k=1;k<=m;k++)
    {
      cin>>i>>j>>w;
      graph[i][j]=w;
      graph[j][i]=w;
    }
    for(i=1;i<=n;i++)
    {
      x[i]=i;
      bestx[i]=i;
    }
    backtrack(2);
    cout<<"Case "<<tmp<<": "<<bestc<<endl;
    bestc=-1;
    c=0;
    
    tmp++;
  }  
  
  return 0;
}

图的m着色问题
1.问题描述
给定无向连通图G和m种不同的颜色。用这些颜色为图G的各顶点着色,每个顶点着一种颜色。是否有一种着色法使G中每条边的2个顶点着不同颜色,求有多少种方法为图可m着色。

2.输入要求:
输入的第一个为测试样例的个数T ( T < 120 ),接下来有T个测试样例。每个测试样例的第一行是顶点数n、边数M和可用颜色数m( n <= 10,M < 100,m <= 7 ),接下来M行,每行两个整数u和v,表示顶点u和v之间有一条边相连。( 1 <= u < v <= n )。

3.输出要求:
对应每个测试样例输出两行,第一行格式为"Case #: W",其中'#'表示第几个测试样例(从1开始计),W为可m着色方案数。

4.样例输入:

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

5.样例输出:

Case 1: 360

6.解决方法:

#include<iostream>
using namespace std;
#define N 100
int m,n,M,a[N][N],x[N],textNum;
int static sum=0;

bool ok(int k)
{
  for(int j=1;j<=n;j++)
  if(a[k][j]&&(x[j]==x[k]))
  return false;
  return true;
}


void backtrack(int t)
{
  if(t>n)
  {
    sum++;
    // for(int i=1;i<=n;i++)
    //cout<<x[i]<<" ";
    //cout<<endl;
  }
  else
  for(int i=1;i<=m;i++)
  {
    x[t]=i;
    if(ok(t))
    backtrack(t+1);
    x[t]=0;
  }
}

int main()
{
  int i,j,z=1;
  cin>>textNum;         //输入测试个数
  while(textNum>0)
  {
    cin>>n;          //输入顶点个数
    for(i=1;i<=n;i++)
    for(j=1;j<=n;j++)
    a[i][j]=0;
    cin>>M>>m;         //输入边的个数、可用颜色数
    for(int k=1;k<=M;k++)   //生成图的邻接矩阵
    {
      cin>>i>>j;
      a[i][j]=1;
      a[j][i]=1;
    }
    /* for(i=1;i<=n;i++){
      for(j=1;j<=n;j++)
      cout<<a[i][j]<<" ";
    cout<<endl;}*/
    for(i=0;i<=n;i++)
    x[i]=0;
    backtrack(1);
    cout<<"Case "<<z<<": "<<sum<<endl;
    sum=0;
        
    textNum--;
    z++;
  }
    
  return 0;
}

相关文章

  • QT已有项目导入工程时注意事项图文详解

    QT已有项目导入工程时注意事项图文详解

    QT开发这几年大大小小项目做了不少,花了点时间对知识点总结整合了一部分,下面这篇文章主要给大家介绍了关于QT已有项目导入工程时注意事项的相关资料,需要的朋友可以参考下
    2023-11-11
  • 解析Linux内核的基本的模块管理与时间管理操作

    解析Linux内核的基本的模块管理与时间管理操作

    这篇文章主要介绍了Linux内核的基本的模块管理与时间管理操作,包括模块加载卸载函数的使用和定时器的用法等知识,需要的朋友可以参考下
    2016-02-02
  • 基于Qt实现的自定义树结构容器

    基于Qt实现的自定义树结构容器

    在Qt框架中,尽管其提供了许多强大的容器类,但缺少一个通用的、灵活的树结构容器,所以本文将设计并实现一个可复用的自定义树结构容器,需要的可以参考下
    2024-12-12
  • Matlab实现绘制高阶版本韦恩图(upset图)

    Matlab实现绘制高阶版本韦恩图(upset图)

    韦恩图随着阶数升高会越来越复杂,当阶数达到7或者以上时几乎没办法绘制,但是使用upset图却可以比较轻易的绘制。本文就来用Matlab实现绘制upset图,需要的可以参考一下
    2023-01-01
  • C++超详细讲解稀疏矩阵

    C++超详细讲解稀疏矩阵

    今天小编就为大家分享一篇关于C++稀疏矩阵的转置思路并实现乘法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2022-05-05
  • 关于C++中sort()函数的用法,你搞明白了没

    关于C++中sort()函数的用法,你搞明白了没

    这篇文章主要介绍了关于C++中sort()函数的用法,并通过三种方法介绍了按降序排列的实现代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-03-03
  • C++指针 详细介绍及总结

    C++指针 详细介绍及总结

    这篇文章主要介绍了C++指针 详细介绍及总结的相关资料,需要的朋友可以参考下
    2016-09-09
  • Qt编写地图之实现跨平台功能

    Qt编写地图之实现跨平台功能

    这篇文章主要介绍了如何利用Qt编写地图应用时实现跨平台功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2022-02-02
  • 基于C语言实现的aes256加密算法示例

    基于C语言实现的aes256加密算法示例

    这篇文章主要介绍了基于C语言实现的aes256加密算法,结合具体实例形式详细分析了C语言实现的aes256加密算法实现步骤与使用技巧,需要的朋友可以参考下
    2017-02-02
  • C++多继承(多重继承)的实现

    C++多继承(多重继承)的实现

    多继承容易让代码逻辑复杂、思路混乱,本文主要介绍了C++多继承(多重继承)的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04

最新评论