主頁 >  其他 > 題解——八數碼難題

題解——八數碼難題

2020-09-16 04:43:34 其他

題解——八數碼

題目(粘貼自洛谷)

題目描述

在3×3的棋盤上,擺有八個棋子,每個棋子上標有1至8的某一數字,棋盤中留有一個空格,空格用0來表示,空格周圍的棋子可以移到空格中,要求解的問題是:給出一種初始布局(初始狀態)和目標布局(為了使題目簡單,設目標狀態為123804765),找到一種最少步驟的移動方法,實作從初始布局到目標布局的轉變,

輸入格式

輸入初始狀態,一行九個數字,空格用0表示

輸出格式

只有一行,該行只有一個數字,表示從初始狀態到目標狀態需要的最少移動次數(測驗資料中無特殊無法到達目標狀態資料)

輸入輸出樣例

輸入 283104765 輸出 4

思路

那么這個題主要的思維難度在于如何設計狀態,很多人都會想到用一個3*3的陣列來模擬這個9宮格,但是實際上是不可行的,因為我們沒有辦法去表示這個狀態下與初始狀態的移動步數(也許可以用哈希表,但博主不會)那么如何來設計我們的狀態呢?其實題目給了我們提示:用一個9位數來表示這個并狀態,與陣列上上的位置一一對應,舉個例子:
123740865

1 2 3
7 4 0
8 6 5
用9位數的話,可以很好的表示到了這個狀態后與初始狀態的移動步數是多少,因為9位數比較大,開陣列浪費空間,我們可以選擇用map,但是有人要問了:如果用9位數的話,我們如何去交換兩個數的位置呢?其實如果是一個陣列的話就比較容易轉換的,相信讀者也注意到了,這里的陣列與我們9位數的狀態之間是可以互相轉化的,我們只需要稍微處理一下,編個函式也罷,
所以這個題的總體思路就是:用9位數作為狀態傳遞,用陣列去模擬交換

A*

因為這個題用到了A*演算法,所以這里就簡單的講講A*是什么.
簡單地說,我們平常的搜索演算法多是沒有目的的搜索,但是呢A*卻是有目的的搜索,好比一個人在操場上,要去國旗旗桿,平常的搜索更像是一個瞎子,最壞的話要把操場每一個位置都找遍才能到達旗桿的位置,但是A*更像是一個正常人,一眼看見旗桿的位置,并朝那個方向走過去,很明顯A*演算法要比BFS或DFS便捷的多,事實也是如此:A*比平常的搜索演算法快得多!,這個題也不例外,
那么如何使用A*呢
我們對每個點定義一個估價函式f(x)=g(x)+h(x),g(x)表示從起始點到x的實際代價,h(x)表示估計的從x到結束點的代價,并要求h(x)小于等于從x到結束點的實際代價,那么每次我們從可行點集合中找到f(x)最小的x,然后搜索他,這個程序可以用優先佇列(即堆)實作,這樣的話可以更快地到達結束點,并保證到達結束點時走的是最優路徑,一般來說,h函式的選擇決定了A*演算法的效率,h函式與實際值的差距越小越好
如果不知道優先佇列是什么,可以去我的博客中的關于STL的講解中看看(包括上文的map),
對于這個題map的選擇有兩種:1.不在應該在的位置上的數的個數;2.所用數距離其應在位置的曼哈頓距離和,

博主選擇第一種(比較好實作)

那么,讓我們來看看代碼吧!

代碼

我們分開來看

定義部分

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>//
#include<queue>//
#include<map>//
#include<sstream>
#define N 100001
#define ll long long
using namespace std;
這里不用細說,但注意一下,帶"//"的,都與STL有關,有興趣的讀者可以自行瀏覽我的講STL的博客(稍微打下廣告
這里有一個define,主要功能是替換,也就是下面的long long 下面都可以打成ll了

map+ans

ll ans;
map<ll,int> f;//f=g+h
map<ll,bool> vis;
這里呢有一個ans,用來儲存答案,兩個map,f是A*中的f函式,(f=g+h),vis用來判重,

優先佇列

struct rode{
	int fh;
	ll zt;
	ll g;
	rode() { };
	rode(int fh,ll zt,ll g) : fh(fh),zt(zt),g(g) { };
};
struct cmp{
	bool operator () (rode a,rode b)
	{
		return a.fh>b.fh;
	}
};
priority_queue<rode,vector<rode>,cmp> q;
這里有一個rode結構體,fh是這個狀態下的f值(A*),zt是這個狀態,g是原始狀態到這個狀態移動所用的步數,在這個結構體中有有兩個函式,叫做建構式是在定義中使用的,在這個題中的意義就是在我們往下面這個優先佇列里輸進資料時能扣簡便些,如果你不清楚哪里簡便,一會看見dfs部分,你就知道了,

A*并不是獨立存在的,這個演算法會依附于其他的搜索演算法,并加快其速度,

至于結構體cmp和多載運算子operator,博主講STL博客中略有介紹,但如果有讀者對多載運算子operator感興趣,可以自行上網查閱,博主只是背了下來,在這里,結構體cmp的作用是讓這個優先佇列q其中元素的排列順序是fh越的越靠前,是的你沒看錯,是,這可以被認為是一個小根堆,
至于最后一行是優先佇列的定義形式,這里不在詳講,

其它

ll qishi,mubiao=123804765;

int a[4][4];

const int fx[]={0,1,-1,0,0};
const int fy[]={0,0,0,1,-1};
這里理解起來就比較簡便了,qishi就是原始狀態,即“起始”,mubiao即“目標”,是目標狀態,下面那個陣列是用來模擬9宮格的,下面的程式將實作這二者之間的轉化,
而下面這兩個陣列,相信打過搜索的讀者都比較熟悉,這里不多解釋,

次要函式部分

就是相對容易一些的函式

轉化1

inline ll zhuanhua1(ll zhuang,ll& x_0,ll& y_0)
{
	for(int i=3;i>=1;i--)
	{
		for(int j=3;j>=1;j--)
		{
			a[i][j]=zhuang%10;
			zhuang/=10;
			if(a[i][j]==0)
			{
				x_0=i;
				y_0=j;
			}
		}
	}
}//over

這里的inline先不用去管他,我聽別人說這個能減少時間,但博主也不知道是什么干什么用的

這個函式實作了9位數狀態到陣列的轉化程序,
常數中zhuang就是我們設計的狀態,至于常數x_0,y_0,你也許已經知道這是什么意思,他們是0的位置的“橫縱坐標”,
這里的“&”是用來回傳數值的,一般來說,在運用這個函式時的變數與這個函式的變數之間沒有關系,但這個符號實作了把數值回傳,例如在我的主函式中:
zhuanhua1(zhuang,dx,dy);
在運行完畢后,dx,dy的值將會是0的位置的橫縱坐標,

這里關于這個符號,有興趣的朋友可以自行上網瀏覽,

至于函式內部嗎,很好理解,相信各位讀者也能看懂,如果仍有不懂的問題,請各位讀者自行探索,

轉化2

ll zhuanhua2()
{
	ll resu=0;
	for(int i=1;i<=3;i++)
	{
		for(int j=1;j<=3;j++)
		{
			resu+=a[i][j];
			resu*=10;
		}
	}
	resu/=10;
	return resu;
}//over
這個函式實作了由陣列到9位數狀態的轉化程序
其實與轉化1是相反的,

這里請千萬不要忘了最后除以10,因為回圈結束后resu是一個10位數,

h函式

int h(ll qi,ll mu)
{
	int an=0;
	ll q=qi,m=mu;
	while(q>0)
	{
		int i=q%10,j=m%10;
		if(i!=j) an++;
		q/=10;m/=10;
	}
	return an;
}//over
這就是A*演算法中的重中之重,h函式,h函式的選擇將直接決定到這個程式運行結果的方方面面,
剛剛在思路里講了,博主選的h函式是不在應在位置上的數的個數,這里qi常數是目前狀態,mu是目標狀態,然后比較他們的每一位,如果不同的話an++,這便是這個函式,沒有我們想象中的那么復雜,最后回傳an,

主要函式部分

dfs+A*

ll dfs(ll zhuang)
{
	if(zhuang==mubiao)
	{
		//return g;
		return q.top().g;
	}
	ll dx,dy;
	zhuanhua1(zhuang,dx,dy);
	int gb=q.top().g;
	q.pop();
	for(int i=1;i<=4;i++)
	{
		int x,y;
		x=dx+fx[i];
		y=dy+fy[i];
		if(x<1||y<1||x>3||y>3) continue;
		swap(a[x][y],a[dx][dy]);
		ll newz;
		newz=zhuanhua2();
		f[newz]=h(newz,mubiao)+gb+1;
		if(!vis[newz]) q.push(rode(f[newz],newz,gb+1));
		swap(a[dx][dy],a[x][y]);
	}
	int next=q.top().zt;
	vis[next]=1;
	return dfs(next);
	vis[next]=0;
}
這里的常數是zhuang,也就是目前搜索到的狀態,
這里如果目前狀態已經是目標狀態,那么優先佇列隊頭元素的g就是正解,

至于原因嘛,可以這么理解,當目前狀態和目標狀態一樣時,h應該是0,而這時f=g+h=g,因為優先佇列是f越小的越往前,所以這里的f自然是最小,其余的f都大,f=g+h,而h還實際上小于實際值,加了個比實際值小的還大,更別提加的是實際值了,這里也說明了為什么h函式要小于實際值,

然后定義了dx,dy,呼叫函式zhuanhua1,這是陣列a中已經至目前狀態所對應的那個“9宮格”,這時gb存盤一下隊首函式的g值(因為下面要用),并彈出隊首元素,
下面有一個回圈,列舉是哪個位置上的數與0這個位置交換,x,y,即這個位置的橫縱坐標,下面緊接著判斷是否越界,如果沒有的話交換這兩個位置的值,并呼叫zhuanhua2,把這個陣列對應的9位數狀態輸入到newz(即new zhuangtai,博主比較喜歡用這種方式定義變數)去,接著如果這個點沒有被搜索過,就把newz的的f值算出來,就等于h函式加gb+1(因為這里再次移動,步數又加1),再把這個newz的f值,它本身,和它的g值,扔進佇列,

這里建構式的便利就顯現了出來,你不用再去構建一個結構體,而可以直接實作入隊操作,

回圈最后,把兩個值交換回來,不影響另外的決策,
回圈結束后,取出f值最小的那個狀態,并把它的vis標記上,然后搜索他,最后回溯,

主函式

int main()
{
	cin>>qishi;
	f[qishi]=h(qishi,mubiao);
	q.push(rode(f[qishi],qishi,0));
	ans=dfs(qishi);
	cout<<ans;
	return 0;
}
這就比較好懂了,輸入qishi值,因為qishi的g值為0,多以這里不用去管,光看h就可以了,然后把它入隊,然后再搜索,然后再輸出,然后,,,就結束了,

結束

那么這篇題解到這里就結束了,如果覺得還可以,請點個推薦,如果對哪里有意見回批評、建議,請在評論區留言,謝謝大家的觀看!

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/53353.html

標籤:其他

上一篇:有沒有大神知道合泰 的BS83B04A-4這塊芯片如何做檢測觸摸按鍵的

下一篇:【資料結構學習日記】資料結構的應用:查詢功能

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more