7-8 旅行售货员
某售货员要到若干城市去推销商品,已知各城市之间的路程(或旅费)。他要选定一条从驻地出发,经过每个城市一遍,最后回到驻地的路线,使总的路程(或总旅费)最小。
输入格式:
第一行为城市数n
下面n行n列给出一个完全有向图,如 i 行 j 列表示第 i 个城市到第 j 个城市的距离。
输出格式:
一个数字,表示最短路程长度。
输入样例:
3
0 2 1
1 0 2
2 1 0
输出样例:
3
简化版代码
解释:下面这个代码是没有进行剪枝的,也就是说没有优化,但是可以过pta,所以我也给出
#include <iostream>
const int N = 20;
bool vis[N];
int n, mp[N][N], ans = 0x3f3f3f3f;
void dfs(int u, int siz, int fee)
{
for (int i = 0; i < n; ++i) {
if (i == u || vis[i]) continue;
vis[i] = true;
dfs(i, siz + 1, fee + mp[u][i]);
vis[i] = false;
}
}
int main()
{
scanf("%d", &n);
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
scanf("%d", &mp[i][j]);
dfs(0, 0, 0);
printf("%d", ans);
return 0;
}
解释:这个代码是在上面这个代码的基础上加上了剪枝的代码,也就是优化了一下,如果只是为了过pta,用上面这份代码就够了
这个是优化的部分代码
if (siz == n && ans > fee) {
ans = fee;
}
if (fee >= ans || siz >= n) return ;
if (siz < n - 1 && vis[0]) return ;
完整代码:
#include <iostream>
const int N = 20;
bool vis[N];
int n, mp[N][N], ans = 0x3f3f3f3f;
void dfs(int u, int siz, int fee)
{
if (siz == n && ans > fee) {
ans = fee;
}
if (fee >= ans || siz >= n) return ;
if (siz < n - 1 && vis[0]) return ;
for (int i = 0; i < n; ++i) {
if (i == u || vis[i]) continue;
vis[i] = true;
dfs(i, siz + 1, fee + mp[u][i]);
vis[i] = false;
}
}
int main()
{
scanf("%d", &n);
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
scanf("%d", &mp[i][j]);
dfs(0, 0, 0);
printf("%d", ans);
return 0;
}
注释版代码
#include <iostream>
const int N = 20;
bool vis[N];
int n, mp[N][N], ans = 0x3f3f3f3f;
// 深度优先搜索函数
void dfs(int u, int siz, int fee)
{
// 如果已经找到了一种方案且费用更低,更新答案
if (siz == n && ans > fee) {
ans = fee;
}
// 如果当前费用已经超过当前答案或者已经选择了足够的点,结束递归
if (fee >= ans || siz >= n) return;
// 如果还需要选择一个点但是第一个点已经被选中,结束递归
if (siz < n - 1 && vis[0]) return;
// 遍历所有未被选择的点
for (int i = 0; i < n; ++i) {
if (i == u || vis[i]) continue;
// 选择一个点并递归
vis[i] = true;
dfs(i, siz + 1, fee + mp[u][i]);
// 恢复状态,回溯
vis[i] = false;
}
}
int main()
{
// 输入点的数量
scanf("%d", &n);
// 输入图的邻接矩阵
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
scanf("%d", &mp[i][j]);
// 从第一个点开始进行深度优先搜索
dfs(0, 0, 0);
// 输出最小费用
printf("%d", ans);
return 0;
}
java版代码
import java.util.Scanner;
public class Main {
static final int N = 20;
static boolean[] vis = new boolean[N];
static int[][] mp = new int[N][N];
static int n, ans = Integer.MAX_VALUE;
// 深度优先搜索函数
static void dfs(int u, int siz, int fee) {
// 如果已经找到了一种方案且费用更低,更新答案
if (siz == n && ans > fee) {
ans = fee;
}
// 如果当前费用已经超过当前答案或者已经选择了足够的点,结束递归
if (fee >= ans || siz >= n) return;
// 如果还需要选择一个点但是第一个点已经被选中,结束递归
if (siz < n - 1 && vis[0]) return;
// 遍历所有未被选择的点
for (int i = 0; i < n; ++i) {
if (i == u || vis[i]) continue;
// 选择一个点并递归
vis[i] = true;
dfs(i, siz + 1, fee + mp[u][i]);
// 恢复状态,回溯
vis[i] = false;
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 输入点的数量
n = scanner.nextInt();
// 输入图的邻接矩阵
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
mp[i][j] = scanner.nextInt();
}
}
// 从第一个点开始进行深度优先搜索
dfs(0, 0, 0);
// 输出最小费用
System.out.println(ans);
}
}
标签:旅行,fee,int,siz,++,vis,ans,售货员
From: https://www.cnblogs.com/aslwr/p/78-travel-salesperson-z1kxmjj.html