算法设计实验六
实验六 利用回溯法解决售货员旅行问题
实验目的
- 掌握回溯法的算法框架(排列树框架);
- 利用回溯法解决售货员旅行问题.
实验内容
1. 回溯法的算法框架(排列树框架)
void backtrack(int t) {
if (t == N) {
output();
} else {
for(int i = t; i < N; i++) {
swap(x[i], x[t]);
if (constraints(t) && bound(t)) backtrack(t+1);
swap(x[i], x[t]);
}
}
}
2. 排列算法
问题描述:打印出 N 个元素的所有排列。
参考实现:
#include <stdio.h>
#include <stdlib.h>
#define N 5
int x[] = {1, 2, 3, 4, 5};
void output() {
int i;
for (i = 0; i < N; i++)
printf(" %d ", x[i]);
printf("\n");
}
void swap(int i, int j) {
int tmp = x[i];
x[i] = x[j];
x[j] = tmp;
}
void perm(int t) {
if (t == N) {
output();
} else {
int i;
for (i = t; i < N; i++) {
swap(i, t);
perm(t + 1);
swap(i, t);
}
}
}
void main() {
perm(0);
}
3.售货员旅行问题
问题描述:某售货员到若干城市推销问题,已知各城市之间的路程,他要选定一条从驻地出发,经过每个城市一遍,最后回到驻地的路线,使总路程最小。(详见教材 P140, P166)
参考实现:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define N 4
int graph[N][N];
int x[] = { 0, 1, 2, 3, 0};
void swap(int a[], int x, int y) {
int t = a[x];
a[x] = a[y];
a[y] = t;
}
int constraints(int t) {
return graph[ x[t-1] ][ x[t] ] != 0;
}
int bound(int t, int w) {
return 1; // 1 == true
}
void output(int w) {
int i;
for (i = 0; i < N; ++i) {
printf("%d -> ", x[i]);
}
w += graph[ x[N-1] ][ 0 ];
printf("0: %d\n", w);
}
void backtrack(int t, int w) {
if (t == N) {
output(w);
} else {
int i;
for (i = t; i < N; ++i) {
swap(x, t, i);
if (constraints(t) && bound(t, w))
backtrack(t + 1, w + graph[ x[t-1] ][ x[t] ]);
swap(x, t, i);
}
}
}
void initGraph();
void main() {
initGraph();
backtrack(1, 0);
}
void addEdge(int v1, int v2, int weight) {
graph[v1][v2] = graph[v2][v1] = weight;
}
void initGraph() {
addEdge(0, 1, 30);
addEdge(0, 2, 6);
addEdge(0, 3, 4);
addEdge(1, 2, 5);
addEdge(1, 3, 10);
addEdge(2, 3, 20);
}
思考
上述实现并没有实现限界函数 bound,正确地实现 bound 函数可以加快搜索解的过程,试实现 bound 函数。
浙公网安备 33010602011771号