算法小课堂(九)分支限界法

这篇具有很好参考价值的文章主要介绍了算法小课堂(九)分支限界法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、概述

1.1概念

分支限界法是一种求解最优化问题的算法,常以广度优先或以最小耗费(最大效益)优先的方式搜索问题的解空间树。其基本思想是把问题的可行解展开,再由各个分支寻找最佳解。

在分支限界法中,分支是使用广度优先策略,依次生成扩展结点的所有分支。限界是在结点扩展过程中,计算结点的上界,搜索的同时剪掉某些分支。

1.2与回溯法区别

求解目标不同

  • 回溯法是找出满足约束条件的所有解
  • 分支限界法是找出满足条件的一个解,或某种意义下的最优解

搜索方式不同

  • 回溯法:深度优先
  • 分支限界法:广度优先或最小耗费优先

1.3分类

队列式分支限界法    

将活结点表组织成一个队列,并按队列的先进先出原则选取下一个结点为当前扩展结点。

优先队列式分支限界法

将活结点表组织成一个优先队列,并按优先队列中规定的结点优先级选取优先级最高的下一个结点为当前扩展结点。

  • 最大优先队列:使用最大堆,体现最大效益优先
  • 最小优先队列:使用最小堆,体现最小费用优先

二、相关问题

2.1  0-1背包问题

问题描述

  • 给定n种物品和一个背包。物品i的重量是wi,其价值为vi,背包的容量为c。
  • 应如何选择装入背包的物品,使得装入背包中物品的总价值最大?
  • 在选择装入背包的物品时,对每种物品i只有2种选择,即装入背包或不装入背包。不能将物品i装入背包多次,也不能只装入部分的物品i。

队列式分支限界法

背包的容量c是30,图解如下: 

分支限界法,算法学习笔记,算法,git

#include<queue>
#include<iostream>
#include<vector>
#include<cstdio>
#include<string.h>
#include<algorithm>
#define N 100
using namespace std;

//记录物品信息
struct goods{
	int wight;//物品重量
	int value;//物品价值
};

//记录各节点信息
struct Node{
	int lv;//记录当前节点层数
	int wei;//当前总重量
	int val;//当前总价值
	int status[N];//当前节点的物品状态数组 0/1
};

int n,bestValue,cv,cw,C;//物品数量,价值最大,当前价值,当前重量,背包容量
int final[N];//最终存储状态
struct goods goods[N];


int BranchBound(){
	queue<Node> que;

	Node n1={0,0,0,{0}};
	que.push(n1);

	while(!que.empty()){
		Node nd;
		nd=que.front();
		int lv=nd.lv;	//当前第几层,可以作为goods[]数组的索引

		//如果是最后一层节点,
		//1. 记录该节点的信息
		//2. 弹出队列
		//3. 并跳过循环
		if(lv>=n){
			if(nd.val>bestValue)
			{
				bestValue=nd.val;
				for(int i=0;i<n;i++)
				{
					final[i]=nd.status[i];
				}
			}
			que.pop();
			continue;
		}

		//判断左孩子节点
		//该节点重量加上 下一个物品
		if(nd.wei+goods[lv].wight<=C)
		{
			//构造左孩子节点
			Node mid = que.front();
			mid.lv+=1;
			mid.val+=goods[lv].value;
			mid.wei+=goods[lv].wight;
			//置左孩子结点的 下一状态位为1
			mid.status[lv]=1;

			//将左孩子入队
			que.push(mid);
		}

		//构造并加入右孩子节点
		Node mid2 =  que.front();
		mid2.status[lv]=0;
		mid2.lv+=1;
		que.push(mid2);

		//将当前访问节点弹出
		que.pop();
	}
	return bestValue;
}

int main()
{
    printf("物品种类n:");
    scanf("%d",&n);
    printf("背包容量C:");
    scanf("%d",&C);
    for(int i = 0; i < n; i++){
        printf("物品%d的重量w[%d]及其价值v[%d]:",i+1,i+1,i+1);
        scanf("%d%d",&goods[i].wight,&goods[i].value);
    }

    int sum3 = BranchBound();

    printf("回溯法求解0/1背包问题:\nX=[");
    for(int i = 0; i < n; i++)
        cout << final[i] <<" ";//输出所求X[n]矩阵
    printf("]   装入总价值%d\n",sum3);
    return 0;

}

优先分支限界法

#include <iostream> // 引入输入输出流头文件
#include <queue> // 引入队列头文件
#include <vector> // 引入向量头文件
#include <algorithm> // 引入算法头文件
using namespace std; // 使用标准命名空间

// 物品结构体
struct Item {
    int weight; // 物品的重量
    int value; // 物品的价值
};

// 节点结构体
struct Node {
    int level; // 节点的层次
    int profit; // 节点的收益
    int weight; // 节点的重量
    int bound; // 节点的上界
    vector<bool> taken; // 节点所选取的物品序列
};

// 优先队列的比较函数
struct CompareNode {
    bool operator()(const Node& a, const Node& b) {
        return a.bound < b.bound; // 按照上界从大到小排序
    }
};

// 计算节点的上界
int calculateBound(Node u, int n, int c, vector<Item>& items) {
    if (u.weight >= c) // 如果节点重量超过背包容量,返回0
        return 0;

    int profitBound = u.profit; // 初始化上界为节点收益
    int j = u.level + 1; // 从下一层开始考虑物品
    int totalWeight = u.weight; // 初始化总重量为节点重量

    while ((j < n) && (totalWeight + items[j].weight <= c)) { // 当物品未考虑完且总重量不超过背包容量时,循环执行
        totalWeight += items[j].weight; // 将物品加入总重量
        profitBound += items[j].value; // 将物品价值加入上界
        j++; // 考虑下一个物品
 }

    if (j < n) // 如果还有物品未考虑完,按照单位价值比例加入上界
        profitBound += (c - totalWeight) * items[j].value / items[j].weight;

    return profitBound; // 返回上界值
}

// 优先队列式分支限界法解决0-1背包问题
int knapsack(int n, int c, vector<int>& w, vector<int>& vv) {
    vector<Item> items(n); // 创建一个物品向量

    for (int i = 0; i < n; i++) { // 遍历输入的重量和价值向量,将其转化为物品结构体存入物品向量中
        items[i].weight = w[i];
        items[i].value = vv[i];
 }

    sort(items.begin(), items.end(), [](const Item& a, const Item& b) {
    return (double)a.value / a.weight > (double)b.value / b.weight;
 }); // 按照单位价值从大到小对物品向量进行排序

    priority_queue<Node, vector<Node>, CompareNode> PQ; // 创建一个优先队列,用于存储节点

    Node u, v; // 定义两个节点变量,u为当前节点,v为扩展节点
    u.level = -1; // 初始化u的层次为-1,表示根节点之前的虚拟节点
    u.profit = 0; // 初始化u的收益为0
    u.weight = 0; // 初始化u的重量为0

    int maxProfit = 0; // 初始化最大收益为0

    u.bound = calculateBound(u, n, c, items); // 计算u的上界值
    PQ.push(u); // 将u压入优先队列中

    while (!PQ.empty()) { // 当优先队列不为空时,循环执行
    u = PQ.top(); // 取出优先队列中的第一个元素,即上界最大的节点,赋值给u
    PQ.pop(); // 弹出优先队列中的第一个元素

    if (u.bound > maxProfit) { // 如果u的上界大于当前最大收益,说明有可能找到更优解,继续扩展子节点,否则剪枝处理
    v.level = u.level + 1; // 将v的层次设为u的下一层,即考虑下一个物品是否放入背包中
    v.weight = u.weight + items[v.level].weight; // 将v的重量设为u的重量加上当前考虑物品的重量,即假设放入背包中的情况
    v.profit = u.profit + items[v.level].value; // 将v的收益设为u的收益加上当前考虑物品的价值,即假设放入背包中的情况
    v.taken = u.taken; // 将v所选取的物品序列设为u所选取的物品序列,即继承父节点的选择情况
    v.taken.push_back(true); // 在v所选取的物品序列末尾添加true,表示当前考虑物品被放入背包中

    if (v.weight <= c && v.profit > maxProfit)
        maxProfit = v.profit;
        /* 如果v的重量不超过背包容量且v的收益大于当前最大收益,
           则将最大收益更新为v的收益,即找到了一个更优解 */

    v.bound = calculateBound(v, n, c, items);
        /* 计算v的上界值 */

    if (v.bound > maxProfit)
        PQ.push(v);
        /* 如果v的上界大于当前最大收益,
           则将v压入优先队列中,等待后续扩展 */

    v.weight = u.weight;
     /* 将v的重量设为u的重量,即假设不放入背包中的情况 */

     v.profit = u.profit;
     /* 将v的收益设为u的收益,即假设不放入背包中的情况 */

     v.taken = u.taken;
     /* 将v所选取的物品序列设为u所选取的物品序列,
        即继承父节点的选择情况 */

     v.taken.push_back(false);
     /* 在v所选取的物品序列末尾添加false,
        表示当前考虑物品没有被放入背包中 */

     v.bound = calculateBound(v, n, c, items);
     /* 计算v的上界值 */

     if (v.bound > maxProfit)
         PQ.push(v);
         /* 如果v的上界大于当前最大收益,
            则将v压入优先队列中,等待后续扩展 */

     }
 }

 return maxProfit;
 /* 返回最大收益值 */
}

int main() {
    int n = 3;
    /* 定义物品数量为3 */

    int c = 30;
    /* 定义背包容量为30 */

    vector<int> w = {16, 15, 15};
    /* 定义一个向量存储每个物品的重量 */

    vector<int> v = {45, 21, 25};
    /* 定义一个向量存储每个物品的价值 */

    int maxProfit = knapsack(n, c, w, v);
    /* 调用背包函数,并将返回值赋给maxProfit变量 */

    cout << "最大价值为:" << maxProfit << endl;

 return 0;
}

 2.2旅行售货员问题  

问题描述:

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

分支限界法,算法学习笔记,算法,git

 结果为: 1 3 2 4

队列式分支限界法 

分支限界法,算法学习笔记,算法,git

#include <iostream>
#include <queue>
#include <vector>
using namespace std;

const int INF = 1e9;

struct Node {
    vector<int> path;  // 当前路径
    vector<bool> visited;  // 记录节点是否已访问
    int cost;  // 当前路径的总代价
    int level;  // 当前节点的层级

    Node(int n) {
        visited.resize(n, false);
        cost = 0;
        level = 0;
    }

    Node(const Node& other) {
        path = other.path;
        visited = other.visited;
        cost = other.cost;
        level = other.level;
    }
};

void printSolution(const vector<int>& path) {
    cout << "最优解是: [";
    for (int i = 0; i < path.size(); i++) {
        cout << path[i] + 1;
        if (i != path.size() - 1) {
            cout << " ";
        }
    }
    cout << "]" << endl;
}

int tsp(vector<vector<int>>& graph, vector<int>& optimalPath) {
    int n = graph.size();

    // 初始化最小代价
    int minCost = INF;

    // 创建初始节点
    Node rootNode(n);
    rootNode.path.push_back(0);  // 起始节点为0
    rootNode.visited[0] = true;
    rootNode.level = 1;

    // 创建队列并将初始节点加入
    queue<Node> q;
    q.push(rootNode);

    // 遍历队列中的节点
    while (!q.empty()) {
        Node currNode = q.front();
        q.pop();

        // 如果当前节点是叶子节点
        if (currNode.level == n) {
            // 加上回到起始节点的代价
            currNode.cost += graph[currNode.path.back()][0];

            // 更新最小代价和最优路径
            if (currNode.cost < minCost) {
                minCost = currNode.cost;
                optimalPath = currNode.path;
            }
        }

        // 遍历当前节点的邻居节点
        for (int i = 0; i < n; i++) {
            if (!currNode.visited[i] && graph[currNode.path.back()][i] != -1) {
                // 创建新节点
                Node newNode = currNode;
                newNode.visited[i] = true;
                newNode.path.push_back(i);
                newNode.cost += graph[currNode.path.back()][i];
                newNode.level = currNode.level + 1;

                // 如果当前路径的代价小于最小代价,则加入队列继续搜索
                if (newNode.cost < minCost) {
                    q.push(newNode);
                }
            }
        }
    }

    return minCost;
}

int main() {
    int n;
    cin >> n;

    // 读取输入的图
    vector<vector<int>> graph(n, vector<int>(n));
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            cin >> graph[i][j];
        }
    }

    // 求解旅行售货员问题
    vector<int> optimalPath;
    int minCost = tsp(graph, optimalPath);
    // 输出结果
    cout << "最优值为: " << minCost << endl;
    printSolution(optimalPath);

    return 0;
}

优先队列式分支限界法 

分支限界法,算法学习笔记,算法,git

#include <iostream>
#include <queue>
#include <vector>
using namespace std;

const int INF = 1e9;

struct Node {
    vector<int> path;  // 当前路径
    vector<bool> visited;  // 记录节点是否已访问
    int cost;  // 当前路径的总代价
    int level;  // 当前节点的层级

    Node(int n) {
        visited.resize(n, false);
        cost = 0;
        level = 0;
    }

    Node(const Node& other) {
        path = other.path;
        visited = other.visited;
        cost = other.cost;
        level = other.level;
    }
};

struct CompareNode {
    bool operator()(const Node& node1, const Node& node2) {
        return node1.cost > node2.cost;  // 按照代价从小到大排序
    }
};

void printSolution(const vector<int>& path) {
    cout << "最优解是: [";
    for (int i = 0; i < path.size(); i++) {
        cout << path[i] + 1;
        if (i != path.size() - 1) {
            cout << " ";
        }
    }
    cout << "]" << endl;
}

int tsp(vector<vector<int>>& graph, vector<int>& optimalPath) {
    int n = graph.size();

    // 初始化最小代价
    int minCost = INF;

    // 创建初始节点
    Node rootNode(n);
    rootNode.path.push_back(0);  // 起始节点为0
    rootNode.visited[0] = true;
    rootNode.level = 1;

    // 创建优先队列并将初始节点加入
    priority_queue<Node, vector<Node>, CompareNode> pq;
    pq.push(rootNode);

    // 遍历优先队列中的节点
    while (!pq.empty()) {
        Node currNode = pq.top();
        pq.pop();

        // 如果当前节点是叶子节点
        if (currNode.level == n) {
            // 加上回到起始节点的代价
            currNode.cost += graph[currNode.path.back()][0];

            // 更新最小代价和最优路径
            if (currNode.cost < minCost) {
                minCost = currNode.cost;
                optimalPath = currNode.path;
            }
        }

        // 遍历当前节点的邻居节点
        for (int i = 0; i < n; i++) {
            if (!currNode.visited[i] && graph[currNode.path.back()][i] != -1) {
                // 创建新节点
                Node newNode = currNode;
                newNode.visited[i] = true;
                newNode.path.push_back(i);
                newNode.cost += graph[currNode.path.back()][i];
                newNode.level = currNode.level + 1;

                // 如果当前路径的代价小于最小代价,则加入优先队列继续搜索
                if (newNode.cost < minCost) {
                    pq.push(newNode);
                }
            }
        }
    }

    return minCost;
}

int main() {
    int n;
    cin >> n;

    // 读取输入的图
    vector<vector<int>> graph(n, vector<int>(n));
    for (int i = 0; i < n; i++) {
        for (int j = 0; j <n;  j++) {
            cin >> graph[i][j];
        }
    }
    // 求解旅行售货员问题
    vector<int> optimalPath;
    int minCost = tsp(graph, optimalPath);

    // 输出结果
    cout << "最优值为: " << minCost << endl;
    printSolution(optimalPath);

    return 0;
}

2.3装载问题

问题描述:

最优装载问题:有一批n个集装箱要装上1艘载重量为C的轮船,其中集装箱i的重量为wi,在不考虑集装箱体积的情况下,如何选择装入轮船的集装箱,使得装入轮船中集装箱的总重量最大

已知最优装载问题的一个实例,n=3,C=30,W={16,15,15},试回答如下问题:

 队列式分支限界法 

分支限界法,算法学习笔记,算法,git

#include <iostream>
#include <queue>
#include <vector>
using namespace std;

struct Node {
    vector<int> load;  // 当前装载情况
    int level;  // 当前节点的层级
    int weight;  // 当前装载的总重量

    Node(int n) {
        load.resize(n, 0);
        level = 0;
        weight = 0;
    }

    Node(const Node& other) {
        load = other.load;
        level = other.level;
        weight = other.weight;
    }
};

void knapsack(int n, int C, const vector<int>& weights) {
    // 初始化最优值和最优解
    int bestValue = 0;
    vector<int> bestLoad(n, 0);

    // 创建初始节点
    Node rootNode(n);
    rootNode.level = 0;

    // 创建队列并将初始节点加入
    queue<Node> q;
    q.push(rootNode);

    // 遍历队列中的节点
    while (!q.empty()) {
        Node currNode = q.front();
        q.pop();

        // 如果当前节点是叶子节点
        if (currNode.level == n) {
            // 更新最优值和最优解
            if (currNode.weight <= C && currNode.weight > bestValue) {
                bestValue = currNode.weight;
                bestLoad = currNode.load;
            }
            continue;
        }

        // 不装载第level物品的子节点
        Node noNode = currNode;
        noNode.level = currNode.level + 1;
        q.push(noNode);

        // 装载第level物品的子节点
        if (currNode.weight + weights[currNode.level] <= C) {
            Node yesNode = currNode;
            yesNode.level = currNode.level + 1;
            yesNode.load[currNode.level] = 1;
            yesNode.weight += weights[currNode.level];
            q.push(yesNode);
        }
    }

    // 输出结果
    cout << "最优值为: " << bestValue << endl;
    cout << "最优解为: [";
    for (int i = 0; i < n; i++) {
        cout << bestLoad[i] << " ";
    }
    cout << "]" << endl;
}

int main() {
    int n, C;
    cin >> n >> C;

    // 读取物品重量
    vector<int> weights(n);
    for (int i = 0; i < n; i++) {
        cin >> weights[i];
    }

    // 求解最优装载问题
    knapsack(n, C, weights);

    return 0;
}

优先队列式分支限界法 分支限界法,算法学习笔记,算法,git

#include <iostream>
#include <queue>
#include <vector>
using namespace std;

struct Node {
    vector<int> load;  // 当前装载情况
    int level;  // 当前节点的层级
    int weight;  // 当前装载的总重量

    Node(int n) {
        load.resize(n, 0);
        level = 0;
        weight = 0;
    }

    Node(const Node& other) {
        load = other.load;
        level = other.level;
        weight = other.weight;
    }
};

struct NodeComparator {
    bool operator()(const Node& a, const Node& b) {
        return a.weight < b.weight;  // 按照节点的权重(装载的总重量)升序排序
    }
};

void knapsack(int n, int C, const vector<int>& weights) {
    // 初始化最优值和最优解
    int bestValue = 0;
    vector<int> bestLoad(n, 0);

    // 创建初始节点
    Node rootNode(n);
    rootNode.level = 0;

    // 创建优先队列并将初始节点加入
    priority_queue<Node, vector<Node>, NodeComparator> pq;
    pq.push(rootNode);

    // 遍历优先队列中的节点
    while (!pq.empty()) {
        Node currNode = pq.top();
        pq.pop();

        // 如果当前节点是叶子节点
        if (currNode.level == n) {
            // 更新最优值和最优解
            if (currNode.weight <= C && currNode.weight > bestValue) {
                bestValue = currNode.weight;
                bestLoad = currNode.load;
            }
            continue;
        }

        // 不装载第level物品的子节点
        Node noNode = currNode;
        noNode.level = currNode.level + 1;
        pq.push(noNode);

        // 装载第level物品的子节点
        if (currNode.weight + weights[currNode.level] <= C) {
            Node yesNode = currNode;
            yesNode.level = currNode.level + 1;
            yesNode.load[currNode.level] = 1;
            yesNode.weight += weights[currNode.level];
            pq.push(yesNode);
        }
    }

    // 输出结果
    cout << "最优值为: " << bestValue << endl;
    cout << "最优解为: [";
    for (int i = 0; i < n; i++) {
        cout << bestLoad[i] << " ";
    }
    cout << "]" << endl;
}

int main() {
    int n, C;
    cin >> n >> C;

    // 读取物品重量
    vector<int> weights(n);
    for (int i = 0; i < n; i++) {
        cin >> weights[i];
    }

    // 求解最优装载问题
    knapsack(n, C, weights);

    return 0;
}

6.4布线问题 

问题描述

印刷电路板将布线区域划分为n×m个方格阵列,如图所示。 精确的电路板布线问题要求确定连接方格a的中点到方格b的中点的最短布线方案。 布线时电路只能沿直线或直角布线。 为避免线路相交,已布线方格做上封闭标记,其他线路布线不允许穿过封闭区域。 为讨论方便,我们假定电路板外面的区域为已加封闭标记的方格。

分支限界法,算法学习笔记,算法,git文章来源地址https://www.toymoban.com/news/detail-738781.html

分支限界法,算法学习笔记,算法,git

到了这里,关于算法小课堂(九)分支限界法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 五种基础算法小结与典型题目分享(动态规划、分治、贪心、回溯、分支限界)

    动态规划是用于解决多阶段决策问题的算法策略。它通过用变量集合描述当前情境来定义“状态”,进而用这些状态表达每个阶段的决策。 每个阶段的状态是基于前面的状态经过某种决策得到的。通过建立状态间的递推关系,并将其形式化为数学递推式,得到“状态转移方程

    2024年01月19日
    浏览(65)
  • 【课设】java:迷宫小游戏(递归与分治、动态规划、贪心算法、回溯法、分支限界法)

    鱼弦:CSDN内容合伙人、CSDN新星导师、全栈领域优质创作者 、51CTO(Top红人+专家博主) 、github开源爱好者(go-zero源码二次开发、游戏后端架构 https://github.com/Peakchen) 递归与分治算法 原理: 递归与分治算法将问题分解为子问题,递归地解决每个子问题,最后将结果合并得到整

    2024年02月02日
    浏览(39)
  • git学习笔记 | 版本管理 - 分支管理

    学习文章1 学习文章2 学习文章3 Git是开源分布式版本控制系统,版本控制是一种记录文件内容变化,查阅特定版本修订情况的系统。 说法1 说法2 虽然有两种说法,但大概意思是相同的,前三个区域都在本地,只有远程仓库不在本地。 本地仓库 = 工作区 + 版本区 工作区:本地

    2024年02月10日
    浏览(48)
  • gitlab应用学习笔记1:创建git~创建分支

    git的核心思想是创建一个仓储库,进行代码更改的跟踪 ||git status 查看你的git仓库发生了什么事情 ||git init 初始化创建一个git仓库 其意义为,在刚刚创建的文件夹my-cool当中建立一个代码仓库,通常情况下我们是无法直接看到里面所包含的内容,因此我们需要用到 || ls -a命令来

    2024年02月04日
    浏览(61)
  • 学习笔记——在IDEA中如何上传git以及git分支的拉取和提交

    1.点加号--新建仓库 2.输入仓库名称即可 3.创建完成 将地址复制,下面要用 将项目上传到远程仓库 1.idea绑定git 2.创建本地库 VCS--Create Git Repository...--OK   此时项目文件名变红 ,说明Git已检测到项目,但没有进行追踪, 3.IDEA添加远程仓库 Git--Manage Remotes... 在弹出框中添加路径

    2024年02月04日
    浏览(64)
  • 实验九 分支限界法

    任务描述 本关任务:编写用分支限界法。 相关知识 为了完成本关任务,你需要掌握:分支限界法。 实验原理 , , 印刷电路板将布线区域分成nm个方格。其中绿色的方格是封锁的,即不能布线的方格。白色的方格是可以布线的。精确的电路布线问题要求确定连接方格a中点到方

    2024年02月12日
    浏览(39)
  • 06分支限界法

    分支限界法与回溯法的区别: (1) 求解目标不同 :回溯法的求解目标是找出解空间树中满足约束条件的所有解,而分支限界法的求解目标则是找出满足约束条件的一个解,或是在满足约束条件的解中找出在某种意义下的最优解。 (2) 搜索方式的不同 :回溯法以 深度优先

    2024年02月06日
    浏览(37)
  • 分支限界TSP(旅行商问题)

    【问题】 TSP 问题(traveling salesman problem) 是指旅行家要旅行 n 个城市, 要求各个城市经历且仅经历一次然后回到出发城市, 并要求所走的路程最短。 【想法】 首先确定目标函数的界[down, up], 可以采用贪心法确定 TSP 问题的一个上界。 如何求得 TSP 问题的一个合理的下界呢

    2024年02月08日
    浏览(47)
  • N皇后问题(分支限界法)

    在 n * n 格的棋盘上放置彼此不受攻击的 n 个皇后。按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题等价于在 n * n 的棋盘上放置 n 个皇后,任何 2个皇后不放在同一行或同一列或同一斜线上。 设计一个解 n 皇后问题的队列式分支

    2024年02月04日
    浏览(35)
  • 分支限界法求0-1背包问题

    (1)画出解空间树 (2)Say如何剪枝 (3)求出最优解 假设物品的个数n=3,背包容量W = 30, 重量w =(16,15,15),价值v =(45,25,25) (1)队列式(FIFO)分支限界法:按照队列 先进先出 (FIFO)原则选取下一个结点为扩展结点。 (2)优先队列式分支限界法:按照优先队列中规定的

    2024年02月13日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包