数据结构与算法:回溯算法约束条件:剪枝详解、示例(C#、C++)与回溯典型例题详解

news2024/11/15 13:30:08

文章目录

  • 一、约束条件
  • 二、剪枝
  • 三、典型例题
  • 四、常用术语
  • 五、示例
    • N 皇后问题 C# 示例
    • N 皇后问题 C++ 示例
  • 六、常见用用回溯算法解决的问题汇总
    • 组合问题:
    • 图论问题:
    • 棋盘游戏问题:
    • 优化问题:
    • 调度问题:
    • 其他问题:
  • 总结

在这里插入图片描述


回溯算法是一种通过探索所有可能的候选解来找出所有解的算法。在解决一些问题时,我们需要设置一些约束条件,以确保候选解的有效性。这些约束条件在算法中起着非常重要的作用,因为它们定义了一个问题的解空间。通常,我们会使用剪枝技术来减少搜索空间,以提高算法的效率。

本文将详细介绍回溯算法中的约束条件、剪枝技术以及一些典型的回溯问题,还会讨论一些常用的术语。

一、约束条件

在回溯算法中,约束条件是非常重要的,因为它们定义了一个问题的解空间。约束条件必须被满足,一个候选解才被认为是有效的。通常,这些约束条件在算法中被用来进行剪枝,即提前排除那些明显不可能产生解的候选解,从而减少搜索空间。

以 N 皇后问题为例,约束条件如下:

  1. 同一列上的两个皇后不能相互攻击。
  2. 同一斜线(对角线和反对角线)上的两个皇后不能相互攻击。

在 0-1 背包问题中,约束条件如下:

  1. 背包的总容量有限。
  2. 每个物品都有一个重量和价值。

二、剪枝

剪枝是回溯算法中用于减少搜索量的技术。有两种主要的剪枝技术:

  • 前剪枝: 在搜索的早期阶段就排除一些不可能产生有效解的分支。例如,在解决 N 皇后问题时,如果一个皇后已经被放置在某个位置,那么与这个位置在同一行、同一列和同一对角线上的所有其他位置都不能放置皇后。

  • 后剪枝: 在搜索的后期阶段消除那些已经确定不可能产生解的分支。例如,在解决 0-1 背包问题时,如果当前的总重量已经超过背包的容量,那么这个分支可以被剪掉,因为不可能产生一个更优的解。

三、典型例题

1. N 皇后问题: 在 N×N 的棋盘上放置 N 个皇后,使得它们不会相互攻击(即没有两个皇后在同一列、同一行或同一对角线上)。
2. 0-1 背包问题: 给定一组物品,每个物品有一个价值和一个重量,需要选择一些物品放入一个给定容量的背包中,使得背包内物品的总价值最大。
3. 旅行商问题(TSP): 给定一组城市和每两个城市之间的距离,找到一条最短的路径,访问每个城市一次并返回起点。

四、常用术语

1. 候选解: 一个潜在的解,它可能满足所有约束条件。
2. 有效解: 一个候选解,它满足所有约束条件,被认为是实际问题中的解。
3. 搜索空间: 所有可能候选解的集合。
4. 路径/分支: 从初始状态到某个状态的一系列决策的集合。
5. 深度优先搜索(DFS): 一种回溯算法的实现方式,它沿着一个分支深入到不能再深入为止,然后回溯到上一个分叉点继续搜索。

五、示例

下面是 N 皇后问题和 0-1 背包问题的 C# 和 C++ 示例代码。

N 皇后问题 C# 示例

using System;
using System.Collections.Generic;

namespace NQueens
{
    class Program
    {
        static void Main(string[] args)
        {
            int n = 8;
            SolveNQueens(n);
        }

        static void SolveNQueens(int n)
        {
            int[] board = new int[n];
            bool[] columns = new bool[n];
            bool[] diag1 = new bool[2 * n - 1];
            bool[] diag2 = new bool[2 * n - 1];

            if (PlaceQueens(board, 0, columns, diag1, diag2))
            {
                Console.WriteLine("解决方案:");
                PrintBoard(board);
            }
            else
            {
                Console.WriteLine("没有找到解决方案。");
            }
        }

        static bool PlaceQueens(int[] board, int row, bool[] columns, bool[] diag1, bool[] diag2)
        {
            if (row == board.Length)
            {
                return true;
            }

            for (int col = 0; col < board.Length; col++)
            {
	             if (columns[col] || diag1[row - col + board.Length - 1] || diag2[row + col])
	                {
	                    continue;
	                }
	
	                columns[col] = true;
	                diag1[row - col + board.Length - 1] = true;
	                diag2[row + col] = true;
	                board[row] = col;
	
	                if (PlaceQueens(board, row + 1, columns, diag1, diag2))
	                {
	                    return true;
	                }
	
	                board[row] = 0;
	                columns[col] = false;
	                diag1[row - col + board.Length - 1] = false;
	                diag2[row + col] = false;
	            }
	
	            return false;
            }

		static void PrintBoard(int[] board)
        {
            for (int i = 0; i < board.Length; i++)
            {
                for (int j = 0; j < board.Length; j++)
                {
                    Console.Write(board[j] == i ? "Q " : ". ");
                }
                Console.WriteLine();
            }
        }
    }
}

N 皇后问题 C++ 示例

#include <iostream>
#include <vector>

using namespace std;

void printBoard(const vector<vector<int>>& board) {
    for (const auto& row : board) {
        for (int column : row) {
            cout << column << " ";
        }
        cout << endl;
    }
}

bool isSafe(const vector<vector<int>>& board, int row, int col, vector<bool>& columns, vector<bool>& diag1, vector<bool>& diag2) {
    for (int i = 0; i < row; i++) {
        if (board[i][col] == 1) {
            return false;
        }
    }

    for (int i = row, j = col; i >= 0 && j >= 0; i--, j--) {
        if (board[i][j] == 1) {
            return false;
        }
    }

    for (int i = row, j = col; i < board.size() && j < board[0].size(); i++, j++) {
        if (board[i][j] == 1) {
            return false;
        }
    }

    return true;
}

bool solveNQueensUtil(vector<vector<int>>& board, int row, vector<bool>& columns, vector<bool>& diag1, vector<bool>& diag2) {
    if (row == board.size()) {
        printBoard(board);
        return true;
    }

    for (int col = 0; col < board[0].size(); col++) {
        if (isSafe(board, row, col, columns, diag1, diag2)) {
            board[row][col] = 1;
            columns[col] = true;
            diag1[row - col + board.size() - 1] = true;
            diag2[row + col] = true;

            if (solveNQueensUtil(board, row + 1, columns, diag1, diag2)) return true;

            board[row][col] = 0;
            columns[col] = false;
            diag1[row - col + board.size() - 1] = false;
            diag2[row + col] = false;
        }
    }
    return false;
}

vector<vector<int>> solveNQueens(int n) {
    vector<vector<int>> board(n, vector<int>(n, 0));
    vector<bool> columns(n, false);
    vector<bool> diag1(2 * n - 1, false);
    vector<bool> diag2(2 * n - 1, false);
    solveNQueensUtil(board, 0, columns, diag1, diag2);
    return board;
}

int main() {
    int n = 4;
    vector<vector<int>> board = solveNQueens(n);
    return 0;
}

六、常见用用回溯算法解决的问题汇总

回溯算法是一种深度优先搜索的变种,它适用于解决那些需要探索所有可能解的问题。这类问题通常具有递归结构,即一个问题的解空间可以被分解为多个子问题,每个子问题都是原问题的一部分。以下是一些可以用回溯算法解决的问题:

组合问题:

  1. 排列问题(Permutations):给定一组数字,找出所有可能的排列。
  2. 组合问题(Combinations):给定一组数字,找出所有可能的组合。

图论问题:

  1. 最小生成树(MST):在无向图中找到一个包含所有顶点的子图,使得边的总权重最小。
  2. 最大匹配(Maximum Matching):在图中发现最大的匹配集合。
  3. 哈密顿路径(Hamiltonian Path):在图中寻找一条经过所有顶点恰好一次的路径。
  4. 中国邮递员问题(Chinese Postman Problem):寻找一条经过所有边恰好一次的路径,使得总权重最小。

棋盘游戏问题:

  1. 八皇后问题(8 Queens):在 8x8 的棋盘上放置 8 个皇后,使它们互不攻击。
  2. 骑士巡游问题(Knight’s Tour):在棋盘上找到一条骑士访问所有方格恰好一次的路径。

优化问题:

  1. 0-1 背包问题(0-1 Knapsack Problem):给定一组物品,每个物品有一个价值和重量,选择一些物品放入一个给定容量的背包中,使得背包内物品的总价值最大。
  2. 旅行商问题(TSP):寻找一条最短的路径,访问每个城市恰好一次并返回起点。
  3. 表达式求值问题(Evaluate Expression):给定一个包含加、减、乘、除和括号的表达式,计算其值。

调度问题:

  1. 课程调度问题(Course Scheduling):在有限的时间内安排多门课程,满足各种约束条件。
  2. 机器调度问题(Machine Scheduling):在有限的时间内安排多个机器的工作任务,满足各种约束条件。

其他问题:

  1. 子集和问题(Subset Sum):给定一个整数数组和一个目标值,判断是否存在一个子集,其和等于目标值。
  2. 数独问题(Sudoku):在 9x9 的网格中填入数字,使得每行、每列和每个 3x3 子网格中都包含 1 到 9 的所有数字。
  3. 汉诺塔问题(Tower of Hanoi):通过移动盘子从一个塔到另一个塔,同时遵守特定的规则。

回溯算法通过递归地尝试所有可能的解,并在发现当前解不满足要求时回溯到上一个状态,尝试其他可能的解。这种方法适用于解决上述问题,并且可以通过剪枝技术来优化搜索过程,减少不必要的计算。

总结

回溯算法是一种强大的算法,可以用来解决各种问题。通过设置约束条件和使用剪枝技术,我们可以有效地减少搜索空间,提高算法的效率。在实际应用中,回溯算法可以帮助我们解决各种问题,如 N 皇后问题、0-1 背包问题、旅行商问题等。希望这篇博客能帮助你更好地理解回溯算法及其应用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1859808.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Study--Oracle-04-SQL练习

一、SQL语句思维导图 二、SQL练习 -- 以employee_id 为排序&#xff0c;列出前5个人 -- FETCH select employee_id,first_name from employees order by employee_id FETCH FIRST 5 rows only; -- 以employee_id 为排序&#xff0c;从第6个人开始 到第10个人 -- offset …

48、基于深度学习的离群值输入向量(matlab)

1、基于深度学习的离群值输入向量原理及流程 基于深度学习的离群值检测的输入向量原理是通过神经网络模型对数据进行学习和表示&#xff0c;在该表示中探测异常样本。其流程大致如下&#xff1a; 数据预处理&#xff1a;将数据进行归一化处理&#xff0c;确保神经网络模型能够…

【MDK5问题】:MDK5无法跳转,并且提示:no browse information available in xxxxx

1、问题&#xff1a; MDK5原来的函数调用可以直接跳转到原函数&#xff0c;但是出现不能跳转原函数的情况&#xff0c;且提示&#xff1a;no browse information available in xxxxx 的情况&#xff1b; 2、解决&#xff1a; 如下图所示&#xff1a;在魔术棒&#xff08;pro…

Springboot启动mongoDB报错后禁用mongoDB自动配置

一、背景 最近在项目当中使用到MongoDB的驱动及相关依赖&#xff0c;发现在启动的时候有MongoDB启动报错信息&#xff0c;目前也不直接使用MongoDB&#xff0c;所以把自动配置这一块在启动的时候去除掉。 二、操作方式 Application启动类&#xff0c;修改启动SpringBootAppli…

【STM32】GPIO复用和映射

1.什么叫管脚复用 STM32F4有很多的内置外设&#xff0c;这些外设的外部引脚都是与GPIO复用的。也就是说&#xff0c;一个GPIO如果可以复用为内置外设的功能引脚&#xff0c;那么当这个GPIO作为内置外设使用的时候&#xff0c;就叫做复用。 STM32F4系列微控制器IO引脚通过一个…

GPT-5:人工智能的新篇章,未来已来

目录 GPT-5&#xff1a;人工智能的新篇章&#xff0c;未来已来 引言 1.人工智能的快速发展和对现代社会的影响 2.OpenAI首席技术官米拉穆拉蒂关于GPT-5发布的消息 3.GPT-5对AI领域的潜在影响和期待 4.迎接GPT-5时代的准备 方向一&#xff1a;GPT-5技术突破预测 1.1 GPT-…

百度大模型安全荣获2024世界智能产业博览会“Find智能科技创新应用典型案例”

6月20日&#xff0c;2024世界智能产业博览会在天津开幕。会议聚焦人工智能、智能网联汽车、智能制造等年度热点议题&#xff0c;由世界智能产业博览会组委会指导&#xff0c;世界智能产业博览会组委会秘书处、中国新一代人工智能战略发展研究院、中国软件行业协会、中国网络空间…

第二证券:港交所上市24周年 市值增长38倍

香港交易及结算所有限公司&#xff08;下称香港交易所&#xff09;于近来举办庆典活动&#xff0c;庆祝上市24周年。 据介绍&#xff0c;自2000年起&#xff0c;香港交易所逐步发展成为全球领先的商场营运机构&#xff0c;也成为连接中国内地与国际商场的主要桥梁。到2024年6月…

3 话题通信-API的使用

目录 (一)常用API 1 初始化 1.1 初始化函数(c++) (1)函数一般表达式: (2)使用 (3)举例(c++) 案例1:argc与argv使用 要求 cmakelists.txt配置 代码 效果图 案例2:options的使用 要求 cmakelists.txt配置 代码 效果图 1.2 初始化函数(python) (…

如何绘制网络安全运营的“谷歌地图”?

正如Google Maps&#xff08;谷歌地图&#xff09;彻底改变了驾车出行时的导航模式一样&#xff0c;通过流程映射绘制一张指导网络安全运营的“电子地图”&#xff0c;可以彻底改变组织理解和管理网络安全运营工作的方式。 现代企业网络安全运营的核心并不是部署防火墙和杀毒软…

如何系统学习机器学习?

我不是计算机专业&#xff0c;第一次接触机器学习还是在研一的时候&#xff0c;当时是看到机器学习可以做号码识别&#xff0c;就觉得好厉害&#xff0c;想学这个。 首次了解到Python这门语言&#xff0c;知道了机器学习可以做什么后&#xff0c;就感觉打开了新世界一样。再后来…

数据质量管理-准确性管理

前情提要 根据GB/T 36344-2018《信息技术 数据质量评价指标》的标准文档&#xff0c;当前数据质量评价指标框架中包含6评价指标&#xff0c;在实际的数据治理过程中&#xff0c;存在一个关联性指标。7个指标中存在4个定性指标&#xff0c;3个定量指标&#xff1b; 定性指标&am…

IT入门知识第六部分《后端开发》(6/10)

目录 后端开发&#xff1a;构建强大的服务端逻辑 1.引言 2.后端技术概述 2.1 数据库 2.2 服务器 2.3 API 2.4 安全性 3.服务器和API 3.1 服务器的作用 3.2 API的作用 4.后端框架 4.1 Node.js 4.1.1 特点 4.1.2 用途 4.1.3 代码案例分析 4.2 Django 4.2.1 特点 …

《Redis设计与实现》阅读总结-1

第 2 章 简单动态字符串&#xff08;SDS&#xff09; 1. Redis使用自己构建一种名为简单动态字符串&#xff08;simple dynamic string ,SDS&#xff09;的抽象类型&#xff0c;作为Redis的默认字符串。 2. SDS的结构&#xff1a; free属性&#xff1a;表示这个SDS没有分配任何…

【SQL Server数据库】熟悉DBMS的基本操作及数据库的创建

目录 一、SQL SERVER基本操作 二、用Management Studio创建数据库 1、使用Management Studio创建数据库bookdb&#xff0c;各项参数采用默认设置。 2、使用Management Studio创建数据库EDUC 3. 在EDUC中创建三个表&#xff0c;根据下面要求创建Student&#xff0c;Course&am…

C语言 | Leetcode C语言题解之第190题颠倒二进制位

题目&#xff1a; 题解&#xff1a; const uint32_t M1 0x55555555; // 01010101010101010101010101010101 const uint32_t M2 0x33333333; // 00110011001100110011001100110011 const uint32_t M4 0x0f0f0f0f; // 00001111000011110000111100001111 const uint32_t M8…

django学习入门系列之第三点《小米商城头标总结》

文章目录 总结往期回顾 总结 body标签&#xff0c;默认有一个边框&#xff0c;造成页面四边都有白色的间距&#xff0c;那该如何去除呢? body{margin: 0; }文本居中 文本水平居中&#xff0c;文本会在这个区域中居中text-align作为HTML元素属性其主要是用来文本水平居中的。 &…

一键模板生成视频解决方案,海量模板,满足多样需求

视频已经成为企业营销、宣传、培训的重要手段&#xff0c;高昂的制作成本、复杂的技术门槛以及繁琐的制作流程&#xff0c;往往让许多企业望而却步。美摄科技凭借其深厚的技术积累和创新能力&#xff0c;推出了面向企业的智能一键模板生成视频解决方案&#xff0c;为企业视频制…

电梯开关状态人员进出检测数据集VOC+YOLO格式2220张4类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;2220 标注数量(xml文件个数)&#xff1a;2220 标注数量(txt文件个数)&#xff1a;2220 标注…

50KW-2500KW水冷式负载组概述

对于需要“针落”安静操作的环境&#xff0c;EAK 负载组为传统风冷装置提供了极具吸引力的替代方案。 该系列负载组是水冷的&#xff0c;允许在受控环境中进行室内安装&#xff0c;而不是在室外安装&#xff0c;因为室外设备暴露在元素中。除了完全相当之外&#xff0c;还非常紧…