C/C++回溯法-哈密顿回路问题

问题描述
在这里插入图片描述
为方便分析问题,我们对一个简单些的图进行分析:
在这里插入图片描述
条件约束
1.加入路径的节点与前一个加入路径的顶点一定是连通的;
2.加入路径的最后一个顶点和第一个顶点一定是连通的;
3.路径上不能出现重复的顶点。

完整代码

#include<stdio.h>
#include<malloc.h>
#define max_v 20      //最大顶点数 
typedef struct Node    //顶点 
{
	int v;
	Node *next;
}Node;
int n;                //实际顶点数 
Node *a[max_v];       //邻接链表头指针 
void creat()          //创建邻接链表 
{
	printf("请输入节点个数:");
	scanf("%d",&n);
	for(int i=0;i<n;i++)
	{
		a[i]=(Node *)malloc(sizeof(Node));
	    a[i]->v=i;
		a[i]->next=NULL; 
	} 
	int num;
	for(int i=0;i<n;i++)
	{   
		printf("请输入与顶点%d相连的顶点个数:",i+1);
		scanf("%d",&num);
		printf("请输入与顶点%d相连的顶点,格式如(1 2 3):",i+1);
		for(int j=0;j<num;j++)
		{	
		    Node *node;
			node=(Node *)malloc(sizeof(Node));
			int x;
			scanf("%d",&x);
			node->v=x-1;
			node->next=a[i]->next;
			a[i]->next=node;
		}
	}
	} 
 void hc()
 {
 		creat();
 		int result[n];          //存放路径的数组 
 		bool visited[n];       //对在路径上的顶点进行标记 
 		for(int i=0;i<n;i++)
 		visited[i]=false;       
 	    result[0]=0;
 	    int k=0;
 	    Node *tmp[n];         //避免回溯时每次都从头节点开始遍历,定义一个新的头指针指向上一次遍历到的顶点 
		 for(int i=0;i<n;i++)
		 tmp[i]=a[i]; 
 	    while(k>-1)
 	    {
 	    	Node *p=tmp[result[k]]->next;
 	    	while(p!=NULL)
 	    	{
 	    		if(!visited[p->v])
 	    		{
 	    			tmp[result[k]]=p;
 	    			result[++k]=p->v;             //相连顶点不在路径上,加入路径中 
 	    			visited[p->v]=true;           //标记已在路径上 
 	    			break;
				 }
				 else
				 p=p->next;
			 }
			 if(p==NULL)                          //与剩余顶点不相连,回溯 
			 {
			visited[result[k]]=false;
			 tmp[result[k]]=a[result[k]];
			  k--;	
			 }
			 else
			 {
			 	if(k==n-1)                 //对最后一个顶点进行验证,是否可以和起点形成回路 
			 	{
			 		Node *q=tmp[result[k]]->next;
			 		while(q!=NULL)
			 		{
			 			if(q->v==0)
			 			break;
			 			q=q->next;
					 }
					 if(q!=NULL)
					 break;
					 else                     //不能形成回路,回溯 
					 {
					 	 visited[result[k]]=false;
					 	 tmp[result[k]]=a[result[k]];
					 	 k--;
					 }	
				 }	
			 }
		 }
		 if(k==-1)
		 printf("无解");
		 else 
		 {
		 	printf("满足条件的一个解路径为:");
		 	for(int i=0;i<n;i++)
		 	printf("%d ",result[i]+1);
		 } 
 }
 
 main()
 {
   hc();
 }

运行结果
在这里插入图片描述

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值