哈密顿绕行世界问题 HDU - 2181(深搜)

LINK
一个规则的实心十二面体,它的 20个顶点标出世界著名的20个城市,你从一个城市出发经过每个城市刚好一次后回到出发的城市。
Input
前20行的第i行有3个数,表示与第i个城市相邻的3个城市.第20行以后每行有1个数m,m<=20,m>=1.m=0退出.
Output
输出从第m个城市出发经过每个城市1次又回到m的所有路线,如有多条路线,按字典序输出,每行1条路线.每行首先输出是第几条路线.然后个一个: 后列出经过的城市.

分析:十二面体,每个点都和其他三个点相接;要求字典序输出,每站的连接站又是字典序给出,所以用for循环回溯;

AC代码1:

#include<stdio.h>
#include<string.h>
int g=1,m,t1,t2,t3;
int a[21][21],book[100],c[21],k;
void dfs(int ans,int x)
{
	int i,j;
	if(ans==19)
	{
		for(i=1;i<=3;i++)
		{
			if((a[x][i]==t1||a[x][i]==t2||a[x][i]==t3)&&!book[a[x][i]])//a指该站的其他连接点 
			{
				c[19]=a[x][i];
				printf("%d: ",k++);
				for(j=0;j<=20;j++)
				printf(" %d",c[j]);
				printf("\n");
				return;
			}		
		}
		return;//两个return不要忘记 
	}
		for(i=1;i<=3;i++)
		{
		if(book[a[x][i]]==0)
		{
			c[ans]=a[x][i];
			book[a[x][i]]=1;
			dfs(ans+1,a[x][i]);
			book[a[x][i]]=0;
		}	
		}
}
int main()
{	
 	int i,j;
	for(i=1;i<=20;i++)
	for(j=1;j<=3;j++)
	scanf("%d",&a[i][j]);
	while(scanf("%d",&m)&&m!=0)
	{
		t1=a[m][1];
		t2=a[m][2];
		t3=a[m][3];
		memset(book,0,sizeof(book));
		memset(c,0,sizeof(c));
		k=1;
		book[m]=1;
		c[0]=m;
		c[20]=m;
		dfs(1,m);//1是控制第几站,m是哪一站 
	}
}

除此以外还可以将相连接的点用p[i][j]=1表示,但是复杂度较高
AC代码2:

#include<stdio.h>
#include<string.h>
using namespace std;
int p[25][25];
int visit[25];
int ans[25];
int sum=1,n;
void dfs(int c,int t)
{
	if(t==20&&p[c][n])                  
	{
		printf("%d: ",sum++);
		for(int i=0;i<=20;i++)          
		{
			printf(" %d",ans[i]);
		}
		printf("\n");
	}
	else
	{
		for(int i=1;i<=20;i++)       
		{
			if(p[c][i]&&visit[i]==0)
			{
				visit[i]=1;      
				ans[t]=i;      
				dfs(i,t+1);
				visit[i]=0;
			}
		}
	}
}
int main()
{
	memset(p,0,sizeof(p));
	for(int i=1;i<=20;i++)
	{
		int a,b,c;
		scanf("%d%d%d",&a,&b,&c);
		p[i][a]=p[i][b]=p[i][c]=p[a][i]=p[b][i]=p[c][i]=1;
	}
	while(~scanf("%d",&n)&&n)
	{
		memset(visit,0,sizeof(visit));
		visit[n]=1;                   
		ans[0]=n;
		ans[20]=n;                   
		dfs(n,1);
	}
}```

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值