問題:
給定乙個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...