搜索_DFS_骑士游历问题

版权声明:本文为博主原创作品, 转载请注明出处! https://blog.csdn.net/solider98/article/details/84517267

问题描述:

        在国际象棋的棋盘(8行×8列)上放置一个马,按照“马走日字”的规则,马要遍历棋盘,即到达棋盘上的每一格,并且每格只到达一次。若给定起始位置(x0,y0),编程探索出一条路径,沿着这条路径马能遍历棋盘上的所有单元格。

        改进的设计思想:如果在每步选择方向时,不是任意选择一个方向,而是经过一定的测试和计算,“预见”每条路的“宽窄”,再选择一条最“窄”的路先走,成功的可能性较大。理由是先走“困难的路”,光明大道留在后面。因为每一格迟早都要走到,与其把困难留在后面,不如先走“困难的路”,这样路就会越走越宽,成功的机会就越大。这种方法称为预见算法. 为每个方向测定一个值――可通路数,它表示该位置上还有多少条通路。在每一格上对8个方向都进行试探,并分析比较,下一步应该选择可通路数值最小的方向走。

        下面给出基于上述设计思想的代码:

//骑士游历问题
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
#define mp make_pair
#define fi first
#define se second
using namespace std;
const int MAX = 100, INF = 0x3f3f3f3f;
const int dx[8] = {-1, -2, -2, -1, 1, 2, 2, 1}, dy[8] = {-2, -1, 1, 2, 2, 1, -1, -2};
typedef pair<int, int> pii;
bool vis[MAX][MAX], ok; vector<pii> path;  int n, parr[MAX][MAX]; 
void dfs(){
	if(path.size() == n * n){
		ok = true; for(int i = 0; i < path.size(); ++i) parr[path[i].fi][path[i].se] = i + 1;
		return;
	}
	int x = path.back().fi, y = path.back().se; 
	pii dir[8]; memset(dir, 0, sizeof(dir)); 
	//将x, y周围的所有结点按可选方案数递增依次加入dir中 
	for(int i = 0; i < 8; ++i){
		dir[i].se = i;
		int a = x + dx[i], b = y + dy[i];
		if(a >= 1 && a <= n && b >= 1 && b <= n && !vis[a][b])
			for(int j = 0; j < 8; ++j){
				int c = a + dx[j], d = b + dy[j];
				if(c >= 1 && c <= n && d >= 1 && d <= n && !vis[c][d]) ++dir[i].fi;
			}
	}
	sort(dir, dir + 8);
	for(int i = 0; i < 8; ++i){
		if(!dir[i].fi && path.size() != n * n - 1) continue;
		int a = x + dx[dir[i].se], b = y + dy[dir[i].se];
		if(a >= 1 && a <= n && b >= 1 && b <= n && !vis[a][b]){
			path.push_back(mp(a, b)), vis[a][b] = true, dfs(); if(ok) return;
			path.pop_back(), vis[a][b] = false;
		}	
	}
}
int main(){
	int x, y; n = 8, cin >> x >> y, vis[x][y] = true, path.push_back(mp(x, y)), dfs();
	for(int i = 1; i <= n; ++i, cout << endl)
		for(int j = 1; j <= n; ++j) cout.width(4), cout << parr[i][j];
	return 0;
}

运行截图:

                                                  

猜你喜欢

转载自blog.csdn.net/solider98/article/details/84517267
今日推荐