C++算法設(shè)計(jì)之馬踏棋盤(pán)的實(shí)現(xiàn)
本文實(shí)例為大家分享了C++算法設(shè)計(jì)之馬踏棋盤(pán)的具體代碼,供大家參考,具體內(nèi)容如下
(一)馬踏棋盤(pán)經(jīng)典算法描述:
(1)馬踏棋盤(pán)是經(jīng)典的程序設(shè)計(jì)問(wèn)題之一,主要的解決方案有兩種:一種是基于深度優(yōu)先搜索的方法,另一種是基于貪婪算法的方法。第一種基于深度優(yōu)先搜索的方法是比較常用的算法,深度優(yōu)先搜索算法也是數(shù)據(jù)結(jié)構(gòu)中的經(jīng)典算法之一,主要是采用遞歸的思想,一級(jí)一級(jí)的尋找,遍歷出所有的結(jié)果,最后找到合適的解。而基于貪婪的算法則是制定貪心準(zhǔn)則,一旦設(shè)定不能修改,他只關(guān)心局部最優(yōu)解,但不一定能得到最優(yōu)解。
【問(wèn)題描述】關(guān)于馬踏棋盤(pán)的基本過(guò)程:國(guó)際象棋的棋盤(pán)為 8*8 的方格棋盤(pán)?,F(xiàn)將"馬"放在任意指定的方格中,按照"馬"走棋的規(guī)則將"馬"進(jìn)行移動(dòng)。要求每個(gè)方格只能進(jìn)入一次,最終使得"馬"走遍棋盤(pán)的64個(gè)方格。
【算法分析】
① 在四角,馬踏日走只有兩個(gè)選擇;
② 在其余部分,馬踏日走有四、六、八不等的選擇。
解決方案:在外層另外加上兩層,確保 8*8 方格中的每一個(gè)格子都有8中不同的選擇;
重點(diǎn):為了確保每個(gè)格子能走日字,而且選擇的可能性等同,初始化除了最外兩層格子標(biāo)記沒(méi)有被訪問(wèn),最外兩層中每個(gè)格子都標(biāo)記為已被訪問(wèn)即可達(dá)到目標(biāo)!
解釋?zhuān)?/span>圖片中標(biāo)記紅色的區(qū)域,初始化時(shí)就默認(rèn)為馬已踏日字,集已被訪問(wèn),而中間的 8*8 的表格標(biāo)記為馬未被訪問(wèn)!
并且每一個(gè)表格中馬在訪問(wèn)時(shí)都有8中不同的選擇,這8中不同的選擇都會(huì)在其相應(yīng)的x和y坐標(biāo)上進(jìn)行追加標(biāo)記;
這8中選擇方式為:
【代碼展示1】:遞歸求解(回溯法求解),列出所有的解,并從中找出從(2,2)位置出發(fā)的合適解:
#include <iostream> #include <stdlib.h> ? using namespace std; ? int chessboard[12][12] = {0}; ? int cnt = 0;?? ??? ??? ?//標(biāo)記馬已走的方格數(shù) int sum = 0;?? ??? ??? ?//標(biāo)記馬走完全程的具體方案數(shù) int move[8][2]={ {2,1},{1,2},{-1,2},{-2,1},{-2,-1},{-1,-2},{1,-2},{2,-1}};?? ?//初始馬當(dāng)前位置向其周?chē)噜彴藗€(gè)日字的 x,y的偏移量 ? //輸出馬踏棋盤(pán)的解? void PrintChess(); //馬踏棋盤(pán)遞歸過(guò)程 void Horse(int x,int y);? ? int main(void){ ?? ?int i,j; ?? ?for(i=0;i<12;i++){ ?? ??? ?for(j=0;j<12;j++){ ?? ??? ??? ?if(i==0 || i==1 || i==10 || i==11 || j==0 || j==1 || j==10 || j==11){ ?? ??? ??? ??? ?chessboard[i][j]=-1;//在 8 * 8 的外層再加上兩層,確保 8 * 8 方格中的每一個(gè)格子都有 8 種不同的日字選擇? ?? ??? ??? ?} ?? ??? ?} ?? ?} ?? ?//從起始位置開(kāi)始求得所有解 ?? ?chessboard[2][2] = ++cnt; ?? ?Horse(2,2);?? ?//遞歸調(diào)用當(dāng)前當(dāng)前位置附近的 8 個(gè)日字,看看是否滿足條件 ?? ?return 0;? }? ? void Horse(int x,int y){?? ??? ?//馬永遠(yuǎn)踏的是 x,y位置,而不是 a,b? ?? ?if(cnt >= 64){?? ??? ?//臨界值,馬走日字全部踏完,成功求出問(wèn)題解?? ?? ?? ??? ?sum++; ?? ??? ?PrintChess(); ?? ??? ?return; ?? ?}? ?? ?for(int i=0;i<8;i++){ ?? ??? ?int a = x + move[i][0];?? ??? ?//拿到當(dāng)前馬位置相鄰的 8 個(gè)日字的 x 坐標(biāo)? ?? ??? ?int b = y + move[i][1];?? ??? ?//拿到當(dāng)前馬位置相鄰的 8 個(gè)日字的 y 坐標(biāo)? ?? ??? ?if(chessboard[a][b] == 0){?? ?//判斷當(dāng)前馬位置相鄰的日字是否已被訪問(wèn)? ?? ??? ??? ?cnt++;?? ??? ??? ??? ??? ?? ?? ??? ??? ?chessboard[a][b]=cnt;?? ?//標(biāo)志已被訪問(wèn) ?? ??? ??? ?Horse(a,b);?? ??? ??? ? ?? ?//從當(dāng)前馬的位置繼續(xù)往下訪問(wèn) ?? ??? ??? ?cnt--;?? ??? ??? ??? ??? ? ?? ??? ??? ?chessboard[a][b]=0; ?? ?//回溯回來(lái)修改其相鄰的日字的訪問(wèn)情況? ?? ??? ?} ?? ?} } ? //輸出馬踏棋盤(pán)的解? void PrintChess(){ ?? ?cout<<endl<<"馬踏棋盤(pán)第 "<<sum<<"組解為:"<<endl; ?? ?int i,j; ?? ?for(i=2;i<10;i++){ ?? ??? ?for(j=2;j<10;j++){ ?? ??? ??? ?cout<<" ?"<<chessboard[i][j];? ?? ??? ?} ?? ??? ?cout<<endl; ?? ?}? }
【問(wèn)題的解】:只列出量?jī)山M解,其余未列出:
【代碼展示2】:貪心算法求解,列出從(2,2)位置出發(fā)的合適解,局部最優(yōu):
#include <iostream> #include <stdlib.h> ? using namespace std; ? /*? typedef struct{ ?? ?int x;?? ??? ??? ?//記錄當(dāng)前馬位置的 x 坐標(biāo)?? ??? ? ?? ?int y;?? ??? ??? ?//記錄當(dāng)前馬位置的 y 坐標(biāo)? ?? ?int i;?? ??? ??? ?//記錄從當(dāng)前馬的位置前往下一個(gè)日字的序號(hào) i (0<i<8)? }StackHorse;? */ ? int StackHorse[100][3]={0};?? ??? ??? ?//申請(qǐng)一個(gè)??臻g(里面存儲(chǔ)的就是 x,y,i三個(gè)具體的變量值),來(lái)標(biāo)記馬走的具體位置? int chessboard[12][12] = {0};?? ??? ?//記錄 8 * 8棋盤(pán)馬走的具體腳印? int cnt = 1;?? ??? ??? ?//標(biāo)記馬已走的方格數(shù) int move[8][2]={ {2,1},{1,2},{-1,2},{-2,1},{-2,-1},{-1,-2},{1,-2},{2,-1}};?? ?//初始馬當(dāng)前位置向其周?chē)噜彴藗€(gè)日字的 x,y的偏移量 ? //輸出馬踏棋盤(pán)的解? void PrintChess(); //馬踏棋盤(pán)遞歸過(guò)程 void Horse(int x,int y); ? int main(void){ ?? ?int i,j; ?? ?for(i=0;i<12;i++){?? ??? ?//初始化馬踏棋盤(pán)的具體值(0代表未被訪問(wèn),1代表已被訪問(wèn),-1代表新加的最外面兩層)? ?? ??? ?for(j=0;j<12;j++){ ?? ??? ??? ?if(i==0 || i==1 || i==10 || i==11 || j==0 || j==1 || j==10 || j==11){ ?? ??? ??? ??? ?chessboard[i][j]=-1; ?? ??? ??? ?} ?? ??? ?} ?? ?} ?? ?Horse(2,2);?? ??? ?//從 (2,2)的位置開(kāi)始跑,求得馬踏棋盤(pán)的一組解 ?? ?PrintChess(); ?? ?return 0;? }? ? //非遞歸求一組解的過(guò)程 void Horse(int x,int y){ ?? ?int top=0,i=0; ?? ?int a,b;?? ??? ??? ??? ?//記錄當(dāng)前馬位置附近的日字坐標(biāo) ?? ?chessboard[x][y]=1;?? ?//標(biāo)記當(dāng)前起始位置已被訪問(wèn)? ? ?? ?StackHorse[top][0]=StackHorse[top][1]=2;?? ?//記錄當(dāng)前馬的位置 ?? ?while(cnt < 64){ ?? ??? ?for(;i<8;i++){ ?? ??? ??? ?a = x + move[i][0]; ?? ??? ??? ?b = y + move[i][1]; ?? ??? ??? ?if(chessboard[a][b] == 0){?? ??? ?//如果當(dāng)前馬位置附近的日字沒(méi)有被訪問(wèn)? ?? ??? ??? ??? ?break;?? ??? ??? ??? ??? ??? ?//跳出循環(huán)? ?? ??? ??? ?} ?? ??? ?} ?? ??? ?if(i<8){?? ??? ??? ??? ??? ?//能夠訪問(wèn)當(dāng)前馬位置附近的日字? ?? ??? ??? ?chessboard[a][b]=++cnt; ?? ??? ??? ?StackHorse[top][2]=i;?? ?//記錄訪問(wèn)當(dāng)前馬位置附近的日字序號(hào)(0<i<8) ?? ??? ??? ?top++;?? ??? ??? ??? ??? ?//top指向新的棧頂 ?? ??? ??? ?StackHorse[top][0]=a;?? ?//向新的棧頂放入馬踏入的 x坐標(biāo)?? ? ?? ??? ??? ?StackHorse[top][1]=b;?? ?//向新的棧頂放入馬踏入的 y坐標(biāo)? ?? ??? ??? ?x=a;?? ??? ??? ??? ??? ?//標(biāo)記新的 x? ?? ??? ??? ?y=b;?? ??? ??? ??? ??? ?//標(biāo)記新的 y? ?? ??? ??? ?i=0; ?? ??? ??? ??? ??? ?//從棧頂馬位置開(kāi)始尋找附近的 8 個(gè)日字? ?? ??? ?} ?? ??? ?else{?? ??? ??? ?//沒(méi)有在當(dāng)前馬位置附近找到符合條件的日字 ? ?? ??? ??? ?cnt--;?? ??? ??? ??? ?//回溯? ?? ??? ??? ?chessboard[x][y]=0; ?? ??? ??? ?top--;?? ??? ?//出棧 ?? ??? ??? ?x=StackHorse[top][0];?? ??? ?//拿到當(dāng)前馬位置的 x 坐標(biāo) ? ?? ??? ??? ?y=StackHorse[top][1];?? ??? ?//拿到當(dāng)前馬位置的 y 坐標(biāo)? ?? ??? ??? ?i=StackHorse[top][2];?? ??? ?//拿到當(dāng)前馬位置前往下一日字的序號(hào)? ?? ??? ??? ?i++; ?? ??? ??? ??? ??? ??? ?//繼續(xù)搜索從當(dāng)前馬位置訪問(wèn)的日字序號(hào)的下一位置繼續(xù)訪問(wèn)? ?? ??? ?}? ?? ?}? ?? ? }? ? //輸出馬踏棋盤(pán)的解? void PrintChess(){ ?? ?cout<<"馬踏棋盤(pán)一組解為:"<<endl; ?? ?int i,j; ?? ?for(i=2;i<10;i++){ ?? ??? ?for(j=2;j<10;j++){ ?? ??? ??? ?cout<<" ?"<<chessboard[i][j];? ?? ??? ?} ?? ??? ?cout<<endl; ?? ?}? }
【問(wèn)題的解】:列出一組解:
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
json error: Use of overloaded operator [] is ambiguous錯(cuò)誤的解決方
今天小編就為大家分享一篇關(guān)于json error: Use of overloaded operator [] is ambiguous錯(cuò)誤的解決方法,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-04-04C語(yǔ)言如何求整數(shù)的位數(shù)及各位數(shù)字之和
這篇文章主要介紹了C語(yǔ)言如何求整數(shù)的位數(shù)及各位數(shù)字之和,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11Unity3D實(shí)現(xiàn)經(jīng)典小游戲Pacman
這篇文章主要介紹了基于Unity3D制作一做個(gè)經(jīng)典小游戲Pacman,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Unity3D有一定的幫助,感興趣的小伙伴可以了解一下2021-12-12基于MATLAB神經(jīng)網(wǎng)絡(luò)圖像識(shí)別的高識(shí)別率代碼
今天小編就為大家分享一篇關(guān)于基于MATLAB神經(jīng)網(wǎng)絡(luò)圖像識(shí)別的高識(shí)別率代碼,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-03-03C語(yǔ)言?使用qsort函數(shù)來(lái)進(jìn)行快速排序
排序方法有很多種:選擇排序,冒泡排序,歸并排序,快速排序等。?看名字都知道快速排序是目前公認(rèn)的一種比較好的排序算法。因?yàn)樗俣群芸欤韵到y(tǒng)也在庫(kù)里實(shí)現(xiàn)這個(gè)算法,便于我們的使用。?這就是qsort函數(shù)2022-02-02詳細(xì)談?wù)凜語(yǔ)言中動(dòng)態(tài)內(nèi)存
在C語(yǔ)言中,編寫(xiě)程序的時(shí)候不能確定內(nèi)存的大小,希望程序在運(yùn)行的過(guò)程中根據(jù)數(shù)據(jù)量的大小動(dòng)態(tài)的分配內(nèi)存,這篇文章主要給大家介紹了關(guān)于C語(yǔ)言中動(dòng)態(tài)內(nèi)存的相關(guān)資料,需要的朋友可以參考下2022-03-03Qt實(shí)現(xiàn)卡牌對(duì)對(duì)碰游戲(附demo)
本文主要介紹了Qt實(shí)現(xiàn)卡牌對(duì)對(duì)碰游戲,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-10-10