7-7 旅行售货员

目录

题目描述

输入格式:

输出格式:

输入样例:

输出样例:

解题思路: 

详细代码:


题目描述

某售货员要到若干城市去推销商品,已知各城市之间的路程(或旅费)。他要选定一条从驻地出发,经过每个城市一遍,最后回到驻地的路线,使总的路程(或总旅费)最小。

输入格式:

第一行为城市数n

下面n行n列给出一个完全有向图,如 i 行 j 列表示第 i 个城市到第 j 个城市的距离。

输出格式:

一个数字,表示最短路程长度。

输入样例:

3
0 2 1
1 0 2
2 1 0

输出样例:

3

解题思路: 

使用dfs回溯算法,搜索所有可能的情况

对于图中样例

3
0 2 1
1 0 2
2 1 0

可以作出如下图

而从1号点出发

有如下路径(这并不是所有情况)

1——>2——>3——>1

1——>3——>2——>1

2——>3——>1——>2

2——>1——>3——>2

3——>2——>1——>3

3——>1——>2——>3

另外的还有

1——>2——>1——>3——>1这种

如果当前的权值和已经超过储存的最小权值则会退出递归,需要剪枝,即提前退出

详细代码:

#include<iostream>
#include<cstring>
using namespace std;
const int N=500;
int dt[N][N];
int st[N];
int n;
int res;
int sum;
int start;
void dfs(int u)
{
	if(sum>res)return ;//如果当前权值大于储存的最小权值就没必要走下去了,剪枝操作
	if(u==start){//回到结束点时进行检查是否满足走过所有顶点的条件
		bool bj=true;
		for(int i=1;i<=n;i++)
		{
			if(!st[i])
			{
				bj=false;//如果有一个没满足标记为false
				break;
			}
		}
		if(bj)
		{
			res=min(res,sum);//满足走过所有顶点则更新答案
		}
	}
	for(int i=1;i<=n;i++)
	{
		if(i==u)continue;
		st[i]++;//走这个点即加1走过的次数
		sum+=dt[u][i];//加入总权值
		dfs(i);
		sum-=dt[u][i];//减去加入的权值
		st[i]--;//回溯返回上一个点,所以当前点被视为少走了一次
	}
}
signed main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			cin>>dt[i][j];
			res+=dt[i][j];//最大值不会超过所有边权值的和
		}
	}
	for(int i=1;i<=n;i++)
	{
		start=i;//记录开始点
		st[i]++;
		sum=0;
		dfs(i);
		st[i]--;
	}
	cout<<res<<endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星与星熙.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值