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

本文探讨了一位售货员如何在多个村庄间寻找最短路径的问题,采用深度优先搜索结合剪枝策略,通过邻接表实现高效路径查找,旨在减少旅行时间和成本。
Description

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

Input

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

Output

最短路程

Sample Input

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

Sample Output

3


解题思路

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

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

因为每个村庄只走一次,so往回走的时候,直接利用邻接矩阵a[root,1]a[root,1]a[root,1]这条路。
但是,我用邻接表,企图利用在,这一题里每条链第一个点必定是111的特性,找到a[root,1]a[root,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);
} 
### DFS算法基于邻接表实现图遍历 深度优先搜索(Depth First Search, DFS)是一种用于遍历或搜索树或图的算法。当使用邻接表作为图的存储结构时,DFS可以通过递归或者栈的方式实现。 以下是基于邻接表DFS算法的核心逻辑描述以及其实现代码: #### 核心逻辑 1. 初始化一个布尔数组 `visited` 来记录哪些节点已经被访问过。 2. 对于每一个未被访问过的节点,调用递归函数 `DFS` 进行深度优先遍历。 3. 在递归过程中,先标记当前节点为已访问并打印其值;随后通过邻接表查找该节点的所有相邻节点,并对这些相邻节点依次递归执行相同的操作[^4]。 #### Python 实现代码 下面是一个完整的Python版本的DFS算法实现,适用于由邻接列表表示的图: ```python from collections import defaultdict class Graph: def __init__(self): self.graph = defaultdict(list) def add_edge(self, u, v): self.graph[u].append(v) def dfs_util(self, v, visited): visited.add(v) print(v, end=" ") for neighbour in self.graph[v]: if neighbour not in visited: self.dfs_util(neighbour, visited) def depth_first_search(self, start_vertex): visited = set() self.dfs_util(start_vertex, visited) # 创建图实例并添加边 graph_instance = Graph() edges = [(0, 1), (0, 2), (1, 2), (2, 0), (2, 3), (3, 3)] for edge in edges: graph_instance.add_edge(*edge) print("Following is the Depth-First Traversal starting from vertex 2:") graph_instance.depth_first_search(2) ``` 此代码定义了一个Graph类来管理图的数据结构和操作方法。其中包含了增加边的方法add_edge() 和执行dfs 的辅助方法dfs_util() 。最后,在main部分创建了具体的图对象并通过指定起始点来进行dfs 遍历演示[^5]。 #### C++ 实现代码 如果偏好C++, 下面提供了一种等效解决方案: ```cpp #include <iostream> #include <list> using namespace std; // 图类声明 class Graph { int V; // 节点数 list<int> *adj; // 指针指向一个大小为V的链表数组 public: Graph(int V); // 构造器 void addEdge(int v, int w); // 添加一条从v到w的新边 void DFSUtil(int v, bool visited[]); // 辅助递归函数 void DFS(int v); // 执行DFS遍历 }; Graph::Graph(int V) { this->V = V; adj = new list<int>[V]; } void Graph::addEdge(int v, int w) { adj[v].push_back(w); } void Graph::DFSUtil(int v, bool visited[]) { visited[v] = true; cout << v << " "; // 递归所有关联节点 list<int>::iterator i; for(i = adj[v].begin(); i != adj[v].end(); ++i){ if(!visited[*i]){ DFSUtil(*i, visited); } } } void Graph::DFS(int v){ bool* visited = new bool[V]; for(int i = 0;i<V;i++) visited[i]=false; DFSUtil(v, visited); delete [] visited; } int main(){ Graph g(4); g.addEdge(0, 1); g.addEdge(0, 2); g.addEdge(1, 2); g.addEdge(2, 0); g.addEdge(2, 3); g.addEdge(3, 3); cout << "Following is Depth First Traversal " << "(starting from vertex 2): \n"; g.DFS(2); return 0; } ``` 这段C++程序同样构建了一个简单的无向图,并展示了如何利用邻接表形式进行DFS遍历。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值