货员的难题(DFS)

货员的难题

这题我在洛谷得了80分,此结果仅供参考
题目描述
某乡有n个村庄(1<n≤40),有一个售货员,他要到各个村庄去售货,各村庄之间的路程s(0<s<1000)是已知的,且A村到B村与B村到A村的路大多不同。为了提高效率,他从商店出发到每个村庄一次,然后返回商店所在的村,假设商店所在的村庄为1,他不知道选择什么样的路线才能使所走的路程最短。请你帮他选择一条最短的路。
输入格式
村庄数n和各村之间的路程(均是整数)。
输出格式
最短的路程。
输入输出样例
输入
3
0 2 1
1 0 2
2 1 0
输出
3
分析
这题我们可以用深搜(DFS)(邻接表)来做
依题意我们可以知道,这题就是个搜索
但是,有一个地方十分特殊
就是其他村庄都走过了,下一个点是起点
这里是不能回溯的
所以要

 if(c[f[i].to]==0)//下一个点你能不能走 
	  {
	 	 c[f[i].to]=1;
	 	 dfs(f[i].to,sum+f[i].s,ans+1);
	 	 c[f[i].to]=0;//回溯 
	  }
	  if(f[i].to==1&&ans==n-1)dfs(f[i].to,sum+f[i].s,ans+1);//下一个点是起点,且其他村庄已走过 

分开来
代码

#include<iostream>
using namespace std;
int tot,n,a,c[45],head[2005];
long long m;
struct stu//结构体 
{
	int to,next,s;
}f[2005];
void add(int x,int y,int s)//邻接表 
{
	tot++;
	f[tot].to=y;//子节点 
	f[tot].next=head[x];//下一个
	f[tot].s=s;//当前值 
	head[x]=tot;//方便下一个找自己 
}
void dfs(int now,long long sum,int ans)//有三个,now是当前村庄,sum是当前路程,ans是通过村庄个数 
{   
	if(ans>=n){if(sum<m)m=sum;return;}//如果通过n个村庄,就说明回到了起点 
	if(sum>=m)return;	//剪枝,超过了最小值就跳过 
	for(int i=head[now];i;i=f[i].next)
	 if(f[i].s+sum<m)//要小于最小值 
	 {
	  if(c[f[i].to]==0)//下一个点你能不能走 
	  {
	 	 c[f[i].to]=1;
	 	 dfs(f[i].to,sum+f[i].s,ans+1);
	 	 c[f[i].to]=0;//回溯 
	  }
	  if(f[i].to==1&&ans==n-1)dfs(f[i].to,sum+f[i].s,ans+1);//下一个点是起点,且其他村庄已走过 
	}
	return; 
}
int main()
{
	m=2147483647;//设很大,找最小 
	cin>>n;
	for(int i=1;i<=n;i++)
	 for(int j=1;j<=n;j++)
	  {
	  	cin>>a;
	  	if(a!=0)//自己不能走自己 
	  	add(i,j,a);
	  }
	c[1]=1;//起点为一 
	dfs(1,0,0);  //初值 
	cout<<m;
} 

谢谢

发布了49 篇原创文章 · 获赞 79 · 访问量 1652

猜你喜欢

转载自blog.csdn.net/weixin_45524309/article/details/103601622