【DFS】【邻接表】售货员的难题

Description

某乡有 n n 个村庄 1 n 40 ( 1 < n <40 ) ,有一个售货员,他要到各个村庄去售货,各村庄之间的路程 s ( 0 s 1000 ) s(0<s<1000) 是已知的,且 A A 村与 B B 村与 B B 村与 A A 村的路大多不同,为了提高效率,他从商店出发到每个村庄一次,然后返回商店所在的村,假设商店所在的村庄为 1 1 ,他不知道选择什么样的路才能使所走的路程最短,请你帮助他选择一条路径。

Input

村庄数 n n 和各村之间的路程(均是整数)

Output

最短路程

Sample Input

3 // 村庄数量
0 2 1 // 村庄 1 到各村的路程
1 0 2
2 1 0

Sample Output

3


解题思路

企图多用一个剪枝,然后把自己剪死了。。。:)

暴力深搜从 1 1 走回 1 1 的情况,记录有没有遍历过所有点。

因为每个村庄只走一次,so往回走的时候,直接利用邻接矩阵 a [ r o o t , 1 ] a[root,1] 这条路。
但是,我用邻接表,企图利用在,这一题里每条链第一个点必定是 1 1 的特性,找到 a [ r o o t , 1 ] a[root,1] 这条路,发现我wa了。。。:)

假设剩下的点之间通过的路全是1,这种最小情况下,目前求的答案还是大于已求出答案,就可以剪掉。
很好,这个剪枝我没错(欢呼雀跃!!!)


#include<iostream>
#include<cstdio>
using namespace std;
struct DT{
	int to,s,next;
}a[2000];
int head[50],n,v[50],num,Gun=10000;
int demo(int sum,int x){//上述的第一个剪枝,不知为何就是错了
	int i;
	for(i=head[x];a[i].next;i=a[i].next);
	return (sum+a[i].s);
}
void DFS(int dep,int x,int sum){
	if(dep>n){
		Gun=min(Gun,sum);
		return; 
	}
	/*上面我原本打的是
	  if(dep==n){
		Gun=min(Gun,demo(sum,x));
		return; 
	  }
	*/
	if(v[1]==1)return;//不加上就wa了
	if(sum+(n-dep+1)>Gun)return;//上述的第二个剪枝
	for(int i=head[x];i;i=a[i].next){
	    if(!v[a[i].to]){
	    	v[a[i].to]=1;//v标记走没走过
	    	DFS(dep+1,a[i].to,sum+a[i].s);
	    	v[a[i].to]=0;
	    }
	}
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	    for(int j=1;j<=n;j++){
	    	int x;
	    	scanf("%d",&x);
	    	if(x){
	    		a[++num].s=x,a[num].to=j,a[num].next=head[i],head[i]=num;//建邻接表
	        	Gun+=a[num].s;//这个Gun是最终答案,至于为什么要加这些乱七八糟的,是因为我忘记无限大怎么打了。。。
	    	}
	    } 
    DFS(1,1,0);
    printf("%d",Gun);
} 
发布了45 篇原创文章 · 获赞 0 · 访问量 360

猜你喜欢

转载自blog.csdn.net/qq_39940018/article/details/103601758