回溯和分支限界详解和实例(八皇后问题,哈密顿回路解析和代码)

回溯和分支限界解决的问题

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

回溯法的内涵

在这里插入图片描述

回溯法的一些实例

n皇后问题

在这里插入图片描述

在这里插入图片描述
这棵树实际上是对称的所以不用画后面的位于3 4 格开始的情况也可以得到其他解

伪代码如下
在这里插入图片描述
在这里插入图片描述

#include <stdio.h>
#include <stdlib.h>
#include<stdio.h>
#include<math.h>
int x[15]={0};
int count=0;
int PLACE(int k)//检测第k个皇后能否放进棋盘
{
    int i=1;
    while(i<k)
    {
        if(x[i]==x[k]||fabs(x[i]-x[k])==fabs(i-k))
            return 0;
        i++;
    }
    return 1;
}
void NQUEENS(int n)
{
    int k=1; //k为当前行号
    x[1]=0;//x[k]为第k行皇后所放的列号
    while(k>0)
    {
        x[k]++;
        while(x[k]<=n&&!PLACE(k))//该列不符合,则放入下一列
          x[k]++;
        if(x[k]<=n)
        {
            if(k==n)
            {
            	count++;
            	if(count==4)
            	{
            		printf("%d\n",count);
            		break;
				}
               printf("%d %d %d %d %d %d\n",x[1],x[2],x[3],x[4],x[5],x[6]);     
            }

            else//判断下一行
            {
                k++; x[k]=0;
            }
        }
        else k--;//没找到,则回溯
    }
    return ;
}
int main()
{
	int n;
	while(scanf("%d",&n)&&n!=0)
	{
		 NQUEENS(n);
    
    count =0;
	}
    return 0;
}



哈密顿回路问题

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

子集和数的问题

在这里插入图片描述
在这里插入图片描述

分支限界法

在这里插入图片描述

实例1:分配工作问题

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
旅行售货员问题(Traveling Salesman Problem,TSP)是一个经典的组合优化问题,其目标是在给定的一组城市和每对城市之间的距离下,找到一条经过每个城市恰好一次且最短的路线。 回溯算法: 回溯算法是一种暴力搜索算法,它通过枚举所有可能的路线来求解问题。在TSP问题中,我们可以从任意一个城市作为起点开始,依次尝试每个城市作为下一个访问的城市,直到所有城市都被访问过,然后返回起点。在尝试每个城市时,我们需要考虑已经访问过的城市,避免出现重复访问的情况。 下面是用C++实现TSP问题的回溯算法的示例代码: ```cpp #include <iostream> #include <vector> #include <algorithm> using namespace std; const int INF = 1e9; int n; // 城市数量 int start; // 起点城市 vector<vector<int>> dist; // 城市之间的距离矩阵 vector<int> path; // 当前路径 vector<bool> visited; // 记录每个城市是否已经访问过 int ans = INF; // 最短路线长度 void backtrack(int cur, int cost) { if (path.size() == n) { // 所有城市都已访问过,更新最短路线长度 ans = min(ans, cost + dist[cur][start]); return; } for (int i = 0; i < n; i++) { // 枚举下一个访问的城市 if (!visited[i]) { // 如果城市未访问过 visited[i] = true; path.push_back(i); backtrack(i, cost + dist[cur][i]); // 继续访问下一个城市 path.pop_back(); visited[i] = false; } } } int main() { cin >> n >> start; dist.resize(n, vector<int>(n)); visited.resize(n, false); path.push_back(start); visited[start] = true; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { cin >> dist[i][j]; } } backtrack(start, 0); cout << ans << endl; return 0; } ``` 分支限界算法: 分支限界算法是一种剪枝搜索算法,它通过对搜索树的节点进行剪枝,来减少搜索的时间和空间复杂度。在TSP问题中,我们可以通过估算当前路径的下界来剪枝,避免搜索无效的路径。 下面是用C++实现TSP问题的分支限界算法的示例代码: ```cpp #include <iostream> #include <vector> #include <queue> #include <algorithm> using namespace std; const int INF = 1e9; int n; // 城市数量 int start; // 起点城市 vector<vector<int>> dist; // 城市之间的距离矩阵 vector<int> path; // 当前路径 vector<bool> visited; // 记录每个城市是否已经访问过 int ans = INF; // 最短路线长度 struct Node { int city; // 当前访问的城市 int cost; // 当前路径的长度 int lb; // 当前路径的下界 vector<bool> visited; // 记录每个城市是否已经访问过 vector<int> path; // 当前路径 bool operator < (const Node& other) const { // 优先队列按照下界从小到大排序 return lb > other.lb; } }; int get_lb() { // 获取当前路径的下界 int sum = 0; for (int i = 0; i < n; i++) { if (!visited[i]) { // 如果城市未访问过 int min_dist = INF; for (int j = 0; j < n; j++) { if (visited[j]) { // 如果城市已经访问过 min_dist = min(min_dist, dist[j][i]); } } sum += min_dist; } } return sum; } void branch_and_bound() { priority_queue<Node> pq; pq.push({start, 0, get_lb(), visited, path}); while (!pq.empty()) { Node cur = pq.top(); pq.pop(); int cur_city = cur.city; int cur_cost = cur.cost; int cur_lb = cur.lb; vector<bool> cur_visited = cur.visited; vector<int> cur_path = cur.path; if (cur_path.size() == n) { // 所有城市都已访问过,更新最短路线长度 ans = min(ans, cur_cost + dist[cur_city][start]); continue; } for (int i = 0; i < n; i++) { // 枚举下一个访问的城市 if (!cur_visited[i]) { // 如果城市未访问过 vector<bool> next_visited = cur_visited; next_visited[i] = true; vector<int> next_path = cur_path; next_path.push_back(i); int next_cost = cur_cost + dist[cur_city][i]; int next_lb = next_cost + get_lb(); if (next_lb < ans) { // 如果当前路径的下界小于最短路线长度,继续搜索 pq.push({i, next_cost, next_lb, next_visited, next_path}); } } } } } int main() { cin >> n >> start; dist.resize(n, vector<int>(n)); visited.resize(n, false); path.push_back(start); visited[start] = true; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { cin >> dist[i][j]; } } branch_and_bound(); cout << ans << endl; return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值