搜索算法講解

搜索算法講解

深度優先搜索-DFS

P1219 [USACO1.5] 八皇后 Checker Challenge

一個如下的 6×66 \times 66×6 的跳棋棋盤,有六個棋子被放置在棋盤上,使得每行、每列有且只有一個,每條對角線(包括兩條主對角線的所有平行線)上至多有一個棋子。

上面的布局可以用序列 2461352\ 4\ 6\ 1\ 3\ 52?4?6?1?3?5 來描述,第 iii 個數字表示在第 iii 行的相應位置有一個棋子,如下:

行號 1234561\ 2\ 3\ 4\ 5\ 61?2?3?4?5?6

列號 2461352\ 4\ 6\ 1\ 3\ 52?4?6?1?3?5

這只是棋子放置的一個解。請編一個程序找出所有棋子放置的解。
并把它們以上面的序列方法輸出,解按字典順序排列。
請輸出前 333 個解。最后一行是解的總個數。

思路

首先思考暴力枚舉解法,注意到每一行只能放一個,那就可以一行一行枚舉,然后判斷是否合法即可。

然后會發現暴力枚舉中有很多不必要的操作,比如說我們枚舉到第3行把棋子放在第3列,發現這個位置是非法的,難么其實我們就沒有必要再往下面的層去枚舉了,應該直接把第3行的棋子放到后面的列繼續枚舉即可。

總結一下現在的方法:就是一行一行的放棋子,如果在該行放置的棋子是合法的,就繼續放下一行的;如果枚舉是非法的,就不用繼續枚舉下一行了,而是更換當前行的棋子。

這種方式稱為回溯算法,我們這里使用深度優先搜索來實現。

DFS板子

void dfs(int k) { // k代表遞歸層數,或者說要填第幾個空if (所有空已經填完了) {// 判斷最優解 / 記錄答案return;}for (枚舉這個空能填的選項) {if (這個選項是合法的) {占位dfs(k + 1) // 下一層遞歸取消占位}}
}

接下來還有個難點,就是如何判斷選項合法。首先行上一定不會沖突,因為我們是一行一行枚舉的,每行只能放一個;然后列的話我們可以創建一個名如used_col的bool列表(當然int列表也可以)去存每一行的使用狀態,為true就是用過了,就不能再該行再次使用,false就是沒用過,就可以在該行使用;然后對角線就比較麻煩,而且對角線有兩種,一種是從左往右上升,一種是從左往右下降的,都要判斷清楚。

我們可以發現,從左往右上升的對角線上的點有一個特點,就是x+y的值都一樣,并且除了該對角線上的點都一定不滿足這個條件;另一種對角線則是x-y的值都一樣。這樣我們就可以開2個數組去記錄對角線的使用狀態,首先看x+y為定值的對角線,我們就只需要用數組記錄這個定值對應的使用情況即可,就是開一個bool數組,定值對應數組下標即可;然后看x-y為定值的對角線,思路和前者相同,但是要注意定值可能為負數,就不能作為數組下標,那么就給定值加上一個較大(比x-y的最小值的絕對值大)的固定的整數再作為數組下標即可。

image-20250703222720691

解題代碼

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL N = 100;LL n, ans = 0;
LL arr[N], used_col[N], used_1[N], used_2[N]; void dfs(int k) {if (k > n) {ans++;if (ans <= 3) {for (LL i = 1; i <= n; i++) cout << arr[i] << " ";cout << endl;}return;	}for (LL i = 1; i <= n; i++) {if (!used_col[i] && !used_1[k + i] && !used_2[k - i + 20]) {arr[k] = i, used_col[i] = 1, used_1[k + i] = 1, used_2[k - i + 20] = 1; // 占位dfs(k + 1); // 遞歸下一層used_col[i] = 0, used_1[k + i] = 0, used_2[k - i + 20] = 0; // 取消占位}}
}int main() {cin >> n;dfs(1);cout << ans;return 0;
}

廣度優先搜索-BFS

深度優先搜索會優先考慮搜索的深度。形象點說,就是不找到一個答案不回頭。當答案在整棵解答樹中比較稀疏時,深度優先搜索可能會先陷人過深的情況,一時半會兒找不到解。有時候需要解決連通性、最短路問題時,可以考慮使用廣度優先搜索。

P1443 馬的遍歷

有一個 n×mn \times mn×m 的棋盤,在某個點 (x,y)(x, y)(x,y) 上有一個馬,要求你計算出馬到達棋盤上任意一個點最少要走幾步。

思路

這題拿dfs做的話很難寫,因為他沒有一層一層的體現。這道題適合的方法是bfs。

廣度優先搜索會優先考慮每種狀態的和初始狀態的距離,形象點說,與初始狀態越接近的情況會優先考慮。再具體一點:每個時刻要做的事情就是從上個時刻每個狀態擴展出新的狀態。

(開始在圖上模擬)

當輸入是 4 4 1 1時,擴展方向如圖(a)。

image-20250704000140254

廣度優先搜索使用隊列實現:先將初始狀態加人到空的隊列中,然后每次取出隊首,找出隊首所能轉移到的狀態,再將其壓入隊列;如此反復,直到隊列為空。這樣就能保證一個狀態在被訪問的時候一定是采用的最短路徑。

當輸入是4 4 1 1時,隊列變化如圖(b)。

BFS板子

Q.push(初始狀態); // 將初始狀態入隊
while (!Q.empty()) {State u = Q.front(); // 取出隊首Q.pop(); // 出隊for (枚舉所有可擴展狀態) // 找到u的所有可達狀態vif (是合法的) // v需要滿足某些條件,如未訪問過、未在隊內等Q.push(v); // 入隊(同時可能需要維護某些信息)}

就本題而言,先建立一個結構體數組用于存儲擴展的結點。先讓起點人隊,然后在隊列取狀態逐個擴展。容易被證明每個點被擴展到時一定是最少步數,這里對應了上面說的與初始狀態越接近的情況會優先考慮。又因為每個點只被擴展了一次,所以以復合度是O(mn)。

解題代碼

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;struct coord {int x, y;
};queue<coord> Q; LL n, m, x, y, ans[410][410];
LL movee[8][2] = {{2, 1}, {-2, -1}, {1, 2}, {-1, -2}, {2, -1}, {-2, 1}, {-1, 2}, {1, -2}};int main() {memset(ans, -1, sizeof(ans));cin >> n >> m >> x >> y;ans[x][y] = 0;Q.push((coord){x, y});while (!Q.empty()) {coord u = Q.front();LL x = u.x, y = u.y;Q.pop();for (LL i = 0; i < 8; i++) {LL xx = x + movee[i][0], yy = y + movee[i][1];if (xx < 1 || xx > n || yy < 1 || yy > m || ans[xx][yy] != -1) continue;Q.push((coord){xx, yy});ans[xx][yy] = ans[x][y] + 1;}}for (LL i = 1; i <= n; i++, puts("")) {for (LL j = 1; j <= m; j++) {cout << ans[i][j] << " ";}}return 0;
}

總結

對于同一個模型,無論使用dfs還是bfs,其解答樹是一樣的,只是搜索順序不一樣。所以通常能用dfs寫的都能用bfs寫,反之也可以,只是寫起來的復雜程度可能不一。

同樣是尋找目標解,dfs尋找操作步驟字典序最小的解,而bfs可以找到步驟最小的解。需要根據題目的性質來決定使用什么搜索算法。

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

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

相關文章

深度學習---Rnn-文本分類

# 導入PyTorch核心庫 import torch # 導入神經網絡模塊 import torch.nn as nn # 導入優化器模塊 import torch.optim as optim # 導入函數式API模塊 import torch.nn.functional as F # 導入數據集和數據加載器 from torch.utils.data import Dataset, DataLoader # 導入NumPy…

20250709解決KickPi的K7開發板rk3576-android14.0-20250217.tar.gz編譯之后刷機啟動不了

【整體替換】 Z:\20250704\rk3576-android14.0\rkbin清理編譯的臨時結果&#xff1a; rootrootrootroot-X99-Turbo:~$ cd 14TB/versions/rk3576-android14.0-20250217k7/ rootrootrootroot-X99-Turbo:~/14TB/versions/rk3576-android14.0-20250217k7$ ll rootrootrootroot-X99-…

怎么創建新的vue項目

首先&#xff0c;新建一個文件點文件路徑&#xff0c;輸入cmd

CIU32L051系列 DMA串口無阻塞性收發的實現

1.CIU32L051 DMA的通道映射由于華大CIU32L051的DMA外設資源有限&#xff0c;DMA只有兩個通道可供使用&#xff0c;對應的通道映射圖如下&#xff1a;2.UART對應的引腳分布及其復用映射CIU32L051對應的UART對應的引腳映射圖如下,這里博主為了各位方便查找&#xff0c;就直接全拿…

飛算 JavaAI 體驗:重塑 Java 開發的智能新范式

飛算 JavaAI 體驗&#xff1a;重塑 Java 開發的智能新范式引言&#xff1a;正文&#xff1a;一、工程化代碼生成&#xff1a;從 "片段拼接" 到 "模塊交付"1.1 傳統工具的局限與突破1.2 代碼質量驗證二、智能重構引擎&#xff1a;從 "問題修復" 到…

深入理解JVM的垃圾收集(GC)機制

引言首先我們來介紹垃圾收集的概念&#xff0c;什么是垃圾收集&#xff1f;垃圾收集 &#xff08;Garbage Collection&#xff0c;GC&#xff09;&#xff0c;顧名思義就是釋放垃圾占用的空間&#xff0c;防止內存爆掉。有效的使用可以使用的內存&#xff0c;對內存堆中已經死亡…

【筆記】國標-機動車輛及掛車分類

源于&#xff1a;GB/T 15089-2001機動車輛及掛車分類 1.L類&#xff1a;兩輪或三輪車輛2.M類&#xff1a;四輪載客車輛3.N類&#xff1a;四輪載貨車輛4.O類&#xff1a;掛車5.G類&#xff1a;其他

VLLM部署DeepSeek-LLM-7B-Chat 模型

一、部署環境準備1. 基礎環境要求操作系統&#xff1a;Linux&#xff08;推薦歐拉系統、Ubuntu 等&#xff09;Python 版本&#xff1a;3.8 及以上依賴工具&#xff1a;pip、git、curl可選依賴&#xff1a;GPU 環境&#xff1a;NVIDIA GPU&#xff08;支持 CUDA 11.7&#xff0…

翱翔的智慧之翼:Deepoc具身智能如何賦能巡檢無人機“讀懂”工業現場

翱翔的智慧之翼&#xff1a;Deepoc具身智能如何賦能巡檢無人機“讀懂”工業現場在百米高的風力發電機葉片頂端&#xff0c;在蜿蜒數十公里的高壓輸電線旁&#xff0c;在油氣管道穿越的崇山峻嶺之上&#xff0c;一架四旋翼無人機正精準地懸停著&#xff0c;它的“眼睛”&#xf…

Java大廠面試實錄:謝飛機的電商場景技術問答(Spring Cloud、MyBatis、Redis、Kafka、AI等)

Java大廠面試實錄&#xff1a;謝飛機的電商場景技術問答&#xff08;Spring Cloud、MyBatis、Redis、Kafka、AI等&#xff09;本文模擬知名互聯網大廠Java后端崗位面試流程&#xff0c;以電商業務為主線&#xff0c;由嚴肅面試官與“水貨”程序員謝飛機展開有趣的對話&#xff…

Kotlin基礎

前言 Decrement&#xff08;遞減&#xff09; → 將一個值減 1 的操作 Predicate&#xff08;謂詞&#xff09; → 返回布爾值&#xff08;邏輯值&#xff09;的函數 Reference&#xff08;引用&#xff09; → 允許使用自定義名稱與對象交互 Runtime&#xff08;運行時&…

預防DNS 解析器安全威脅

DNS 是互聯網的重要基礎&#xff0c;例如 Web 訪問、email 服務在內的眾多網絡服務都和 DNS 息息相關&#xff0c;DNS 的安全則直接關系到整個互聯網應用能否正常使用。 DNS 解析器的作用是將用戶輸入的域名轉換為對應的 IP 地址&#xff0c;以便計算機能夠準確地定位并連接到…

Windows下VScode配置FFmpeg開發環境保姆級教程

相關準備 提前在本地開發環境中配置好mingw64或者msys2開發工具集。 安裝VScode軟件。 下載Windows版本的FFmpeg相關庫 下載地址&#xff1a;https://ffmpeg.org/download.html 下載步驟&#xff1a;如下圖。 下載后的文件&#xff1a;包含了可執行文件ffmpeg、ffpl…

Lecture #19 : Multi-Version Concurrency Control

CMU15445課程筆記多版本并發控制 多版本并發控制講的是Mvcc。 即維護單個邏輯對象的多個物理版本&#xff0c; 這樣當一個事務讀取某個對象的時候不會阻塞其他事務寫入該對象&#xff1b; 反之亦然。 但是Mvcc不保護寫寫沖突&#xff0c; 對于這種情況&#xff0c; 可能需要其兩…

imx6ul Qt運行qml報錯This plugin does not support createPlatformOpenGLContext!

imx6ul運行qml的Qt程序報錯This plugin does not support createPlatformOpenGLContext!1、開發環境2、問題復現3、解決辦法第一種方法第二種方法4、結論1、開發環境 主板&#xff1a;imx6ul Qt版本&#xff1a;5.9.6 文件系統&#xff1a;buildroot 問題描述&#xff1a;現需…

軟考中項系統集成第 5 章:軟件工程全流程考點拆解,備考邏輯清晰

備考系統集成項目管理工程師的小伙伴們&#xff0c;福利來啦&#xff01;今天開始為大家帶來《系統集成項目管理工程師&#xff08;第 3 版&#xff09;》考點的思維導圖&#xff0c;今天帶來的是第5章。第 5 章聚焦軟件工程&#xff0c;涵蓋軟件工程定義、軟件需求、軟件設計、…

ICLR 2025 | InterpGN:時間序列分類的透明革命,Shapelet+DNN雙引擎驅動!

在Rensselaer理工學院、Stony Brook大學與IBM Research的合作下&#xff0c;本文聚焦于如何在時間序列分類任務中兼顧性能與可解釋性。傳統深度學習模型雖然準確率高&#xff0c;卻常被詬病為“黑盒”&#xff0c;難以贏得如醫療等高風險領域的信任。為此&#xff0c;作者提出了…

使用ENO將您的JSON對象生成HTML顯示

ENO 是簡單易用&#xff0c;性能卓越&#xff0c;自由靈活開源的 WEB 前端組件&#xff1b;實現 JSON 與 HTML 互操作的 JavaScript 函數庫。沒有任何其它依賴&#xff0c;足夠輕量。 WEBPack NPM 工程安裝。 npm install joyzl/eno 然后在JS中引用 import "joyzl/eno…

7.12 卷積 | 最小生成樹 prim

lc1900.模擬比賽算出兩個指定選手最早和最晚能在第幾輪碰到。還是建議dfs捏模擬比賽&#xff0c;找出兩個特定選手&#xff08;firstPlayer和secondPlayer&#xff09;最早和最晚相遇的輪次。1. 定義了一個“選手”結構體&#xff0c;包含兩個屬性a&#xff08;戰斗力&#xff…

LVS-NAT模式配置

目錄 1、負載調度器配置 配置IP地址 安裝ipvsadm 開啟路由轉發功能 加載ip_vs模塊 啟動ipvsadm服務 配置負載分配策略 查看驗證 2、web節點配置 3、測試 1、負載調度器配置 配置IP地址 增加一塊網卡 cd /etc/sysconfig/network-scripts/ cp ifcfg-ens192 ifcfg-ens…