騎士周遊問題

2021-08-25 08:44:53 字數 2040 閱讀 4500

問題:

給定乙個n*n的棋盤,乙個馬從任意位置出發,按照馬移動的規則,在不重複走任意乙個點的前提下走完所有點,即跳n*n步以後需要遍歷了整個棋盤。

思路:首先就是暴力搜尋,dfs+回溯。

#include 

#include

#include

using

namespace

std;

const

int n = 8;//棋盤的邊長

int chess[n][n];//標記

int move[8][2] = ,,,,,,, };

int backnum = 0;//回溯次數

int resultnum,resultcount=0;//想要的解的個數,當前解的個數

void showtrail();//輸出棋盤,顯示路徑

int main()

void dfs(int x, int y, int cnt )

//如果解的個數達到了,立刻返回,不再尋找

if( resultcount==resultnum )

return;

for( int i=0; i<8; ++i )

}return;

}void showtrail()

}

執行結果:

發現耗費時間太長了,迭代次數非常大(這是在n=7的情況下執行的)。

這個問題可以貪心地進行選擇,從而增大成功找到路徑的概率,其基本思想為:當馬從點(x,y)移動時,假如可以跳到k個可行的位置,那麼先跳到最難達到的那個點。

先把難到達的點走了,剩下的點都是比較容易到達的點,那麼後面能走完的機率就大一些。反之,如果先把容易到達的點給走了,最後面發現那些難到達的點不能滿足(並且這個機率比較大),那麼前面就會浪費非常多的步驟。

#include 

#include

#include

#include

#include

using

namespace

std;

const

int n = 8;//棋盤的邊長

const

int inifite = 999999;//無窮大

int chess[n][n];//標記並記錄路徑

int move[8][2] = ,,,,,,, };//移動方式

int backnum = 0;//記錄回溯次數

int resultnum,resultcount=0;//想要的解的個數,當前解的個數

struct next;

bool cmp( next a, next b )

void dfs(int x, int y, int cnt )

//如果解的個數達到要求,就停止。

if( resultcount==resultnum )

vector

v; for( int i=0; i<8; ++i ) );

}sort( v.begin(), v.end(), cmp );

for( int i=0; iint x1 = x + move[v[i].dir_index][0];

int y1 = y + move[v[i].dir_index][1];

//cout =0&&x1=0&&y1//cout

dfs( x1, y1, cnt+1 );

++backnum; //回溯次數加1

chess[x1][y1] = 0;}}

return;

}void showtrail()

}int road_count(int x, int y)

執行結果:

相同條件下,回溯次數明顯減少了幾個數量級。

騎士周遊問題

問題 給定乙個n n的棋盤,乙個馬從任意位置出發,按照馬移動的規則,在不重複走任意乙個點的前提下走完所有點,即跳nxn步以後需要遍歷了整個棋盤。思路 首先就是暴力搜尋,dfs 回溯。include include include using namespace std const int n 8 棋...

15騎士周遊問題(馬踏棋盤問題)

輸出5 5棋盤的騎士周遊的方法數 include include define x 5 define y 5 int chess x y 二維陣列的初始化,兩個大括號 int count 0 void print printf n 這裡的 n放置也非常巧妙,一行之後換行 printf n 一趟走完也...

BNU 4184 騎士周遊列國

直接dfs 肯定 tle 需要加乙個剪枝。include include include includeusing namespace std int mp 8 8 n,nn const int fx const int fy struct node int cmp node a,node b re...