算法课的作业,C语言编写,分享一下。
linux下gcc编译通过(需要-std=c99参数)
输入:第一行为矩阵的大小,为 1~1000 的自然数,第二行以后是矩阵的值。例如:
5
0 14 30 5 6
10 0 11 4 3
4 6 0 5 6
15 10 13 0 2
13 3 4 11 0
输出:第一行是最优代价,第二行是路线。例如对上述输入,对应输出应为:
25
1 4 5 2 3 1
附件中是测试数据
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#define INFINITY ((u_short) 0xFFFF)
#define INIT_CAPACITY 64
typedef unsigned int u_int;
typedef unsigned short u_short;
void printResult();
void init();
void clear();
void babSearch(u_int, u_int);
void babSearchLeft(u_int, u_int, u_int);
void babSearchRight(u_int, u_int, u_int);
u_int estimate();
u_int estLeft(u_int row, u_int col);
u_int estRight(u_int row, u_int col);
static u_int n;
static u_short *mat = 0;
static u_int selectedPathLen = 0;
static u_int bound = (u_int)0xFFFFFFFF;
static u_int origin = 0;
static u_int *path;
static struct{
u_int size;
bool *row;
bool *column;
} visited;
typedef struct{
u_int row;
u_int column;
} Node;
Node *newNode(u_int row, u_int column);
void deleteNode(Node *node);
inline Node *newNode(u_int row, u_int column){
Node *node = malloc(sizeof(Node));
node->row = row;
node->column = column;
return node;
}
inline void deleteNode(Node *node){
free(node);
}
typedef struct{
Node **nodes;
u_int size;
u_int capacity;
} Stack;
Stack stk;
void stack_init(Stack *s){
s->size = 0;
s->capacity = INIT_CAPACITY;
s->nodes = malloc(sizeof(Node *) * INIT_CAPACITY);
}
void stack_destroy(Stack *s){
free(s->nodes);
s->nodes = 0;
s->size = 0;
}
void stack_push(Stack *s, Node *n){
if(s->size == s->capacity){
s->capacity *= 2;
Node **tmp = malloc(sizeof(Node *) * s->capacity);
memcpy(tmp, s->nodes, sizeof(Node *) * s->size);
free(s->nodes);
s->nodes = tmp;
}
s->nodes[s->size++] = n;
}
Node* stack_pop(Stack *s){
Node *ret = 0;
if(s->size != 0){
ret = s->nodes[--s->size];
if(s->size == s->capacity / 3){
s->capacity /= 2;
Node **tmp = malloc(sizeof(Node *) * s->capacity);
memcpy(tmp, s->nodes, sizeof(Node *) * s->size);
free(s->nodes);
s->nodes = tmp;
}
}
return ret;
}
void babSearch(u_int currentValue, u_int start){
if(visited.size == n-1){ //all nodes are visited
u_int row_l;
u_int col_l;
for(row_l = 0; row_l < n; ++row_l){
if(!visited.row[row_l]) break;
}
for(col_l = 0; col_l < n; ++col_l){
if(!visited.column[col_l]) break;
}
stack_push(&stk, newNode(row_l, col_l));
if(currentValue < bound){
bound = currentValue;
for(u_int i = 0; i < stk.size; ++i){
//path[i] = stk.nodes[i]->row;
path[i] = stk.nodes[i]->row + 1;
}
}
deleteNode(stack_pop(&stk));
return;
}
int ci = -1;
u_short min = INFINITY;
for(u_int j = 0; j < n; ++j){
if(visited.column[j]) continue;
if(mat[start*n+j] < min){
min = mat[start*n+j];
ci = j;
}
}
if(ci == -1){ //WHY?!
return;
}
u_int el = estLeft(start, ci);
u_int er = estRight(start, ci);
if(el <= er){ //goto left first
if(el < bound){
babSearchLeft(el, start, ci);
}
if(er < bound){
babSearchRight(er, start, ci);
}
}else{ //goto right first
if(er < bound){
babSearchRight(er, start, ci);
}
if(el < bound){
babSearchLeft(el, start, ci);
}
}
}
inline void babSearchLeft(u_int currentValue, u_int row, u_int col){
stack_push(&stk, newNode(row, col));
selectedPathLen += (u_int)mat[row*n+col];
u_short raw = mat[col*n+col];
mat[col*n+col] = INFINITY;
visited.row[row] = true;
visited.column[col] = true;
visited.size++;
babSearch(currentValue, col);
mat[col*n+col] = raw;
visited.row[row] = false;
visited.column[col] = false;
visited.size--;
selectedPathLen -= (u_int)mat[row*n+col];
deleteNode(stack_pop(&stk));
}
inline void babSearchRight(u_int currentValue, u_int row, u_int col){
u_short raw = mat[row*n+col];
mat[row*n+col] = INFINITY;
babSearch(currentValue, row);
mat[row*n+col] = raw;
}
inline u_int estLeft(u_int row, u_int col){
selectedPathLen += (u_int)mat[row*n+col];
visited.row[row] = true;
visited.column[col] = true;
visited.size++;
u_int ret = estimate() + selectedPathLen;
visited.row[row] = false;
visited.column[col] = false;
visited.size--;
selectedPathLen -= (u_int)mat[row*n+col];
return ret;
}
inline u_int estRight(u_int row, u_int col){
u_int raw = mat[row*n+col];
mat[row*n+col] = INFINITY;
u_int ret = estimate() + selectedPathLen;
mat[row*n+col] = raw;
return ret;
}
static u_short *minEachRow = 0;
static bool *usedColumn = 0;
u_int estimate(){
u_int ret = 0;
memset(minEachRow, 0, sizeof(u_short) * n);
memset(usedColumn, 0, sizeof(bool) * n);
for(u_int i = 0; i < n; ++i){
if(visited.row[i]) continue; //deleted row
u_short min = INFINITY;
u_int columnIndex = 0;
for(u_int j = 0; j < n; ++j){
if(visited.column[j]) continue; //deleted column
if(mat[i*n+j] < min){
min = mat[i*n+j];
columnIndex = j;
}
}
if(min == INFINITY){
ret = INFINITY;
goto L;
}
ret += min;
minEachRow[i] = min;
usedColumn[columnIndex] = true;
}
for(u_int j = 0; j < n; ++j){
if(visited.column[j]) continue; //deleted column
if(!usedColumn[j]){
u_short min = INFINITY;
for(u_int i = 0; i < n; ++i){
if(visited.row[i]) continue; //deleted row
if(mat[i*n+j] == INFINITY) continue;
u_int r = (u_int)mat[i*n+j] - (u_int)minEachRow[i];
if(r < min){
min = r;
}
}
if(min == INFINITY){
ret = INFINITY;
goto L;
}
ret += min;
}
}
L:
return ret;
}
void init(){
scanf("%u", &n);
visited.size = 0;
visited.row = malloc(sizeof(bool) * n);
visited.column = malloc(sizeof(bool) * n);
for(u_int i = 0; i < n; ++i){
visited.row[i] = false;
visited.column[i] = false;
}
path = malloc(sizeof(u_int) * n);
mat = malloc(sizeof(u_short) * n * n);
u_int i = 0;
while(i < n * n){
scanf("%u", &mat[i]);
if(mat[i] == 0){
mat[i] = INFINITY;
}
++i;
}
stack_init(&stk);
minEachRow = malloc(sizeof(u_short) * n);
usedColumn = malloc(sizeof(bool) * n);
}
void clear(){
free(visited.row);
free(visited.column);
free(path);
if(mat != 0){
free(mat);
mat = 0;
}
stack_destroy(&stk);
free(minEachRow);
free(usedColumn);
}
void printResult(){
printf("%d\n", bound);
for(u_int i = 0; i < n; ++i){
printf("%d ", path[i]);
}
printf("%d\n", path[0]);
}
int main(void){
init();
babSearch(0, origin);
printResult();
clear();
return 0;
}
分享到:
相关推荐
在本项目中,开发者使用了Delphi编程语言来实现TSP的一种解决策略——分支限界法(Branch and Bound)。Delphi是一种基于Object Pascal的高效能、面向对象的开发工具,它的编译器和集成开发环境(IDE)使得创建桌面...
分枝定界法(Branch and Bound Method)是一种用于求解离散和组合优化问题的通用算法。在TSP问题中,分枝定界法通过系统地枚举所有可能解,同时使用上界和下界来剪枝,缩小搜索空间,从而找到问题的最优解或验证不...
整数规划的求解方法多种多样,其中较为著名的是分枝定界法(branch and bound)。该方法是由组合优化专家Beasley, J.E.等人提出的,通过不断分支和边界限定来寻找最优解。 #### 资本预算案例分析 假设存在四个项目,...
分支定界法求解TSp问题的分析研究以及matlab实现
【分支定界法(Branch and Bound)】 分支定界法是一种全局优化策略,常用于解决整数规划问题。它通过将问题空间划分为子问题并逐步缩小搜索范围来寻找最优解。在TSP中,分支定界通常涉及创建一棵包含所有可能旅行...
MATLAB分支定界法求解,大家
为了解决这个问题,人们发展出多种近似算法,其中分支限界法(Branch and Bound)是一种有效的方法。 分支限界法是通过构建一棵搜索树来寻找问题的最优解。这棵树的每个节点代表问题的一个部分解,而边则表示将部分...
分支定界算法, 分支定界算法 分支定界算法 branch and bound
分支定界法(Branch and Bound)是一种在计算机科学和优化问题中寻找最优解的系统化搜索方法。它通过建立一个搜索树,逐步缩小可能的解空间来避免不必要的计算,从而提高求解效率。在图像识别领域,特别是滑动窗口...
分枝定界(Branch and Bound)算法是一种在组合优化问题中寻找最优解的搜索方法,广泛应用于解决诸如旅行商问题、0-1背包问题等复杂优化问题。它结合了分治策略和剪枝技巧,通过系统地枚举所有可能的解空间分支,...
【分支定界法】是优化问题中的一种高效算法,尤其适用于解决整数规划问题,如旅行商问题(TSP)。旅行商问题是一个经典的组合优化问题,目标是在访问一系列城市并返回起点时找到最短的路径,每个城市只能访问一次。...
本文将探讨B&B的主要原则,并通过三个例子来说明该方法及其不同的设计考虑因素:对称旅行商问题(Symmetric Travelling Salesman Problem, STSP)、图划分问题(Graph Partitioning Problem, GPP)以及二次分配问题...
在这个问题中,我们通常采用数学优化的方法来解决,其中分枝限界法(Branch and Bound)是一种有效的全局搜索策略。 分枝限界法结合了深度优先搜索和剪枝策略,以避免无效的搜索空间,确保找到最优解。在货郎担问题...
分枝定界(Branch and Bound,B&B)算法是一种有效解决整数规划问题的方法,它结合了分治策略和搜索树的概念来寻找全局最优解。本项目的目标是使用编程语言,如Matlab或Python,实现一个通用的分枝定界算法,用于...
解决TSP问题的方法众多,其中分支与界法(Branch and Bound)是一种有效的搜索策略,它能够确保找到全局最优解,但其计算复杂度较高。 分支与界法的核心思想是通过构建一棵搜索树来遍历所有可能的解,并利用界函数...
分枝定界(Branch and Bound, B&B)是一种有效的算法,用于求解这类问题,特别是当问题规模较大时。本节将深入探讨分枝定界法在MATLAB中的应用及其在解决整数和混合整数规划问题中的价值。 MATLAB作为一个强大的...
总结来说,分支定界法是解决整数规划问题的关键工具,通过迭代地划分问题空间并结合线性规划松弛来逐步逼近整数解,确保找到全局最优解。这种方法虽然计算量较大,但在很多实际问题中,它提供了寻找最优解的系统化...
Branch and Bound(分支限界)算法是解决这类问题的一种有效策略,尤其在结合多目标优化时,能够帮助我们在众多可能的解中找到一组最优或接近最优的解决方案。 多目标优化通常涉及到多元函数的最优化,其中每个目标...