回溯算法之N皇后

一? ?什么是回溯算法

回溯算法(Backtracking Algorithm)是一種用于解決組合優化問題的算法,它通過逐步構建候選解并進行驗證,以尋找所有滿足特定條件的解。回溯算法通常應用于在給定約束條件下枚舉所有可能解的問題,如組合、排列、子集等。

回溯算法的基本思想是通過遞歸的方式進行搜索,每一步都嘗試擴展當前的解,直到找到滿足條件的解或者確定無解。在搜索的過程中,如果當前的解不滿足約束條件,就會回溯到上一步進行其他選擇,繼續搜索。

回溯算法的一般步驟如下:

  1. 定義問題的解空間,確定問題的約束條件。
  2. 通過遞歸的方式搜索解空間,每一步都進行選擇,并進行約束條件的檢查。
  3. 如果當前的選擇滿足約束條件,則繼續遞歸地進行下一步選擇。
  4. 如果當前的選擇不滿足約束條件,進行回溯,撤銷當前選擇,返回上一步繼續搜索其他選擇。
  5. 當搜索完成后,得到所有滿足條件的解。

回溯算法的時間復雜度通常較高,因為它需要枚舉所有可能的解。在某些情況下,可以通過剪枝等優化策略來減少搜索空間,提高算法效率。

回溯算法在很多問題中都有應用,例如八皇后問題、0-1背包問題、圖的遍歷等。它是一種非常經典和常用的算法思想,對于解決組合優化問題具有重要的作用。

通常解該類題目時,我們要確定解的空間,從而很好的利用回溯算法來解決該類題目。


二? ?何為解空間

? ? ? 解空間(Solution Space)是指在給定問題的約束條件下,所有可能的解的集合。它包含了問題的所有合法解。

? ? ? 解空間的具體形式取決于問題的性質和約束條件。對于某些問題,解空間可能是一個有限的集合,例如在數獨游戲中,解空間是由符合數獨規則的所有數字填充方案組成的集合。而對于其他問題,解空間可能是一個無限的集合,例如在連續優化問題中,解空間是由實數構成的無限維空間。

? ? ?解空間是問題求解的關鍵概念之一。在解決問題時,我們通常需要在解空間中搜索滿足特定條件的解。回溯算法、枚舉法、剪枝算法等求解方法都是基于對解空間的搜索。

? ? ? 解空間的大小直接影響了問題的復雜性和求解算法的效率。如果解空間非常大,問題的求解可能會非常困難,需要耗費更多的時間和資源。因此,在實際應用中,優化算法常常通過剪枝、啟發式搜索等技術來減小解空間的規模,以提高求解效率。

總之,解空間是問題求解中描述所有可能解的概念,通過搜索解空間,我們可以找到滿足問題要求的解或者找到最優解。

對于大多數該類問題的解空間都是樹的形式,集合的大小構成了樹的寬度,遞歸的深度構成的樹的深度。


三? ?回溯算法的模板

下面是回溯算法的一般模板:

void backtracking(參數) {if (終止條件) {存放結果;return;}for (選擇:本層集合中元素(樹中節點孩子的數量就是集合的大小)) {//橫向遍歷處理節點;//這里一般可能進行剪枝操作backtracking(路徑,選擇列表); // 遞歸,縱向遍歷回溯,撤銷處理結果}
}

這是一個基本的回溯算法模板,其中的關鍵點包括:

  1. 定義終止條件:當滿足終止條件時,表示找到了一個解或者不再需要繼續搜索,可以進行相應的操作,如輸出結果或返回。

  2. 遍歷選擇列表:遍歷所有可能的選擇,通常使用循環結構,對于每個選擇,進行相應的操作。

  3. 做出選擇:根據當前選擇,更新狀態或路徑,表示對問題的一次選擇。

  4. 遞歸進入下一層決策樹:根據當前選擇,進入下一層決策樹,即進行下一步的選擇。

  5. 撤銷選擇:在回溯到上一層之前,需要撤銷當前選擇,恢復狀態或路徑,以便進行下一個選擇。

在實際應用中,根據具體問題的不同,模板中的代碼需要進行相應的修改和擴展,以適應問題的特點和約束條件。同時,通過剪枝、優化等技巧,可以對模板進行改進,提高算法的效率。

需要注意的是,回溯算法是一種暴力搜索的方法,解空間的規模很大時,可能會導致算法效率低下。因此,在使用回溯算法時,需要根據問題的規模和特點進行合理的優化和剪枝,以提高算法的性能。


四? ?回溯算法例題之N皇后問題

按照國際象棋的規則,皇后可以攻擊與之處在同一行或同一列或同一斜線上的棋子。n?皇后問題?研究的是如何將?n?個皇后放置在?n×n?的棋盤上,并且使皇后彼此之間不能相互攻擊。

給你一個整數?n?,返回所有不同的?n?皇后問題?的解決方案。每一種解法包含一個不同的?n 皇后問題?的棋子放置方案,該方案中?'Q'?和?'.'?分別代表了皇后和空位。

4*4的棋盤擺放結果如下:

解題思路:

  1. 定義一個 N × N 的棋盤,使用一個二維數組或其他數據結構表示。初始化棋盤的所有位置為空。

  2. 從第一行開始,逐行放置皇后。對于每一行,遍歷該行的每一個位置,嘗試將皇后放置在當前位置。

  3. 在放置皇后之前,檢查是否滿足以下條件:

    • 當前位置的同一列沒有其他皇后。
    • 當前位置的左上方和右上方(對角線)沒有其他皇后。
  4. 如果滿足上述條件,將皇后放置在當前位置,并將該位置標記為已占用。

  5. 繼續遞歸地處理下一行,重復步驟 3 和步驟 4。

  6. 如果已經放置了 N 個皇后,表示找到了一個可行解,將該解保存起來。

  7. 回溯到上一步,撤銷對當前位置的選擇,繼續嘗試下一個位置。

  8. 當所有的位置都嘗試完畢或者已經找到了所有的可行解時,算法結束。

  9. 返回所有的可行解。

? ? 我們先以3*3的棋盤來看它的解空間,如圖所示:

不難看出解空間對應的是樹的結構,我們可以套用模板進行解決:

void Backtrack(char bord[][N],int n,int row){if(row>=n){//遞歸出口print(bord,n);//如果滿足直接打印結果count++;//用來記錄解的數量printf("\n");return ;}else{for(int colum=0;colum<n;colum++){//橫向遍歷if(isselect(bord,row,colum,n)){//如果滿足放置條件bord[row][colum] = 'Q';Backtrack(bord,n,row+1);//進行遞歸,選擇下一行的格子bord[row][colum] = '*';//回溯}}}
}

?【完整代碼】

#include <stdio.h>
#include <stdbool.h>
#define N 100int count=0;
void print(char bord[][N],int n){for(int i=0;i<n;i++){for(int j=0;j<n;j++){if(bord[i][j] == 'Q'){printf("  Q");}else{printf("  *");} }printf("\n");} 
}bool isselect(char bord[][N], int row, int colum,int n) {for(int j=0;j<row;j++){//判斷列if(bord[j][colum]=='Q'){return false;}}for(int i=row,j=colum;i>=0&&j>=0;i--,j--){//判斷左上角if(bord[i][j]=='Q'){return false;}}for(int i=row,j=colum;i>=0&&j<n;i--,j++){//判斷右上角if(bord[i][j]=='Q'){return false;}}return true;}void Backtrack(char bord[][N],int n,int row){if(row>=n){print(bord,n);count++;printf("\n");return ;}else{for(int colum=0;colum<n;colum++){if(isselect(bord,row,colum,n)){bord[row][colum] = 'Q';Backtrack(bord,n,row+1);bord[row][colum] = '*';}}}
}int main()
{int n;printf("請輸入皇后個數:\n");scanf("%d",&n);char bord[N][N]={'*'};printf("皇后擺放形式如下:\n");Backtrack(bord,n,0);printf("%d后問題共有%d種擺放方案 ",n,count);return 0;
}

【運行效果】

部分資料參考:代碼隨想錄;?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/211816.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/211816.shtml
英文地址,請注明出處:http://en.pswp.cn/news/211816.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Git—文件添加查看刪除修改

目錄 1.添加文件—場景一 2.查看.git文件 3.添加文件—場景三 4.修改文件 5.版本回退 6.撤銷修改 7.刪除文件 1.添加文件—場景一 在包含.git的目錄下新建?個ReadMe文件&#xff0c;我們可以使用 git add 命令可以將文件添加到暫存 區&#xff1a; ●添加一個或多個文…

Matlab數學建模算法之小波神經網絡詳解

&#x1f517; 運行環境&#xff1a;Matlab &#x1f6a9; 撰寫作者&#xff1a;左手の明天 &#x1f947; 精選專欄&#xff1a;《python》 &#x1f525; 推薦專欄&#xff1a;《算法研究》 &#x1f510;#### 防偽水印——左手の明天 ####&#x1f510; &#x1f497; 大家…

vue的屬性

key 預期&#xff1a;number | string | boolean (2.4.2 新增) | symbol (2.5.12 新增) key 的特殊 attribute 主要用在 Vue 的虛擬 DOM 算法&#xff0c;在新舊 nodes 對比時辨識 VNodes。如果不使用 key&#xff0c;Vue 會使用一種最大限度減少動態元素并且盡可能的嘗試就地…

2022藍橋杯c組求和

題目名字 求和 題目鏈接 題意 輸入的每個數都要兩兩相乘&#xff0c;然后再加起來&#xff0c;求最后總和&#xff1b; 思路 每個數乘這個數的前綴和即可 算法一&#xff1a;前綴和 實現步驟 先把前綴和寫出來再寫for循環每個數都乘以自己的前綴和&#xff1b; 實現步驟 直接…

存儲成本降71%,怪獸充電歷史庫遷移OceanBase

怪獸充電作為共享充電寶第一股&#xff0c;業務增長迅速&#xff0c;以至于業務架構不停地增加組件。在驗證 OceanBase 可以簡化架構并帶來更大的業務價值后&#xff0c;首次嘗試在歷史庫中使用 OceanBase 替代 MySQL&#xff0c;存儲成本降低 71%。本文為怪獸充電運維架構部王…

Docker 入門

Docker 入門 基礎 不同操作系統下其安裝包、運行環境是都不相同的&#xff01;如果是手動安裝&#xff0c;必須手動解決安裝包不同、環境不同的、配置不同的問題 而使用Docker&#xff0c;這些完全不用考慮。就是因為Docker會自動搜索并下載MySQL。注意&#xff1a;這里下載…

【C++】輸入輸出流 ⑥ ( cout 標準輸出流對象 | cout 常用 api 簡介 | cout.put(char c) 函數 )

文章目錄 一、cout 標準輸出流對象1、cout 標準輸出流對象簡介2、cout 常用 api 簡介 二、cout.put(char c) 函數1、cout.put(char c) 函數 簡介2、代碼示例 - cout.put(char c) 函數 一、cout 標準輸出流對象 1、cout 標準輸出流對象簡介 cout 是 標準輸出流 對象 , 是 ostrea…

端口被占用 --- 解決方案

問題描述 加速服務啟動失敗&#xff0c;443端口被magentproc(1576)占用。請關掉占用443端口的程序或者嘗試使用系統代理模式。 問題解決 按下 win R 打開 輸入cmd 輸入命令 netstat -ano | findstr 443 找到 0.0.0.0:443 對應的端口 (1576) 按下 ctrl shift esc, 打開任務管…

綜述 2023-IEEE-TCBB:生物序列聚類方法比較

Wei, Ze-Gang, et al. "Comparison of methods for biological sequence clustering." IEEE/ACM Transactions on Computational Biology and Bioinformatics (2023). https://ieeexplore.ieee.org/document/10066180 被引次數&#xff1a;1&#xff1b;研究背景&am…

力扣題:數字與字符串間轉換-12.13

力扣題-12.13 [力扣刷題攻略] Re&#xff1a;從零開始的力扣刷題生活 力扣題1&#xff1a;442. 數組中重復的數據 解題思想&#xff1a;直接相除即可 class Solution(object):def optimalDivision(self, nums):""":type nums: List[int]:rtype: str"&qu…

Transformer 簡介

Transformer 是 Google 在 2017 年底發表的論文 Attention Is All You Need 中所提出的 seq2seq 模型。Transformer 模型的核心是 Self-Attention 機制&#xff0c;能夠處理輸入序列中的每個元素&#xff0c;并能計算其與序列中其他元素的交互關系的方法&#xff0c;從而能夠更…

再見了Future,圖解JDK21虛擬線程的結構化并發

Java為我們提供了許多啟動線程和管理線程的方法。在本文中&#xff0c;我們將介紹一些在Java中進行并發編程的選項。我們將介紹結構化并發的概念&#xff0c;然后討論Java 21中一組預覽類——它使將任務拆分為子任務、收集結果并對其進行操作變得非常容易&#xff0c;而且不會不…

Unity中Shader黑白閥值后處理效果

文章目錄 前言一、我們先來PS看一下黑白閥值的效果二、使用step(a,b)函數實現效果三、實現腳本控制黑白閥值1、在Shader屬性面板定義控制閥值變量2、把step的a改為_Value3、在后處理腳本設置公共成員變量,并且設置范圍為&#xff08;0&#xff0c;1&#xff09;4、在Graphics.B…

Cocos Creator:創建棋盤

Cocos Creator&#xff1a;創建棋盤 創建地圖三部曲&#xff1a;1. 創建layout組件2. 創建預制體Prefab&#xff0c;做好精靈貼圖&#xff1a;3. 創建腳本LayoutSprite.ts收尾工作&#xff1a; 創建地圖三部曲&#xff1a; 1. 創建layout組件 使用layout進行布局&#xff0c;…

優化瑞芯微rk3566 tf卡速度uhs SDR104

環境 開發板&#xff1a;orangepi3B CPU:rk3566 TF卡速度標識&#xff1a;C10&#xff0c;U3&#xff0c;V30 起因 對于tf卡啟動的系統來說&#xff0c;io會成為一個很關鍵的瓶頸&#xff0c;所以總希望系統能跑得快一點。我手頭用的是一張金士頓的高性能tf卡&#xff0c;開…

四十三、Redis基礎

目錄 一、認識NoSql 1、定義&#xff1a; 2、常見語法 3、與關系型數據庫&#xff08;SQL&#xff09;的區別&#xff1a; 二、認識Redis 1、定義&#xff1a; 2、特征&#xff1a; 3、Key的結構&#xff1a; 三、安裝Redis 四、Redis常見命令 1、數據結構介紹 2、…

關于DNS服務器地址總是127.0.0.1且無法解析域名地址

問題 筆者嘗試nslookup解釋域名時&#xff0c;出現服務器變成本地環回口地址&#xff0c;導致無法解析域名 C:\Users\Zsy>nslookup www.baidu.com 服務器: UnKnown Address: 127.0.0.1*** UnKnown 找不到 www.baidu.com: Server failed排查思路 嘗試關閉虛擬網卡&#…

CSS的邏輯組合偽類

CSS 的邏輯組合偽類有 4 種&#xff0c;分別是&#xff1a;:not()、:is()、:where()和&#xff1a;has()。 否定偽類:not() :not 偽類選擇器用來匹配不符合一組選擇器的元素。由于它的作用是防止特定的元素被選中&#xff0c;它也被稱為反選偽類&#xff08;negation pseudo-…

Torch2TRT編譯和使用踩坑

前言 Torch2TRT是英偉達提供的開源Pytorch到TensorRT模型的轉化工具。相對于其他Pytorch模型轉TensorRT的方式&#xff0c;我認為這是最簡單和容易上手的方式。但是該工具并不成熟&#xff0c;在安裝和使用過程中有一些坑。 遇到的問題 1. fatal error: xxxxxx.h: No such f…

自動化測試框架 —— pytest框架入門篇

今天就給大家說一說pytest框架。 今天這篇文章呢&#xff0c;會從以下幾個方面來介紹&#xff1a; 01、pytest框架介紹 pytest 是 python 的第三方單元測試框架&#xff0c;比自帶 unittest 更簡潔和高效&#xff0c;支持非常豐富的插件&#xff0c;同時兼容 unittest 框架。…