ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Warnsdorff‘s algorithm 完成骑兵游行(Knight tour)问题

2021-07-26 21:58:07  阅读:268  来源: 互联网

标签:return algorithm min Warnsdorff Knight ++ cell int deg


问题描述:

在一个8x8(或者nxn)的棋盘上,一个骑兵(马)走日(对角)能否遍历整个棋盘。

http://en.wikipedia.org/wiki/Knight%27s_tour

Warnsdorff's algorithm: Heruistic 剪枝,排除不需要的回溯路

规则如下两条:

1)我们可以从棋盘上任意一处开始移动

2)我们每次移动到最近,最狭隘(周围没遍历过点最少)的点(be more greedy!)

算法的基本结构:

1. 任意选取点P为棋盘上起点

2. 标记P为1

3. 重复以下动作从2-64:

        1. S 作为P能移动到的点的set

        2. 标记P 为S里最小accesibility

        3. 标记P 为现在的移动次数

4. 返回标记的数组

import java.util.*;
import java.util.concurrent.ThreadLocalRandom;

public class knight_tour {
	
	public static final int N = 8;
	
    //cx,cy记录可以移动的位置 8 种
	public static final int cx[] = {1, 1, 2, 2, -1, -1, -2, -2};
    public static final int cy[] = {2, -2, 1, -1, 2, -2, 1, -1};
	
    class Cell {
        int x;
        int y;
     
        public Cell(int x, int y)
        {
            this.x = x;
            this.y = y;
        }
    }
    
    //判断是否在棋盘内
    boolean limits(int x, int y) {
        return ((x >= 0 && y >= 0) && (x < N && y < N));
    }
    
    //判断是否能走
    boolean isempty(int a[], int x, int y){
        return (limits(x, y)) && (a[y * N + x] < 0);
    }
    
    //找到每个点的degree 方便选择剪枝
    int getDegree(int a[], int x, int y) {
        int count = 0;
        for (int i = 0; i < N; ++i)
            if (isempty(a, (x + cx[i]),(y + cy[i])))
                count++;
        return count;
    }
    
    // 选择下一个位置
    Cell nextMove(int a[], Cell cell)
    {
        int min_deg_idx = -1, c,
            min_deg = (N + 1), nx, ny;
 
        //随机选一个开始点
        int start = ThreadLocalRandom.current().nextInt(1000) % N;
        for (int count = 0; count < N; ++count) {
            int i = (start + count) % N;
            nx = cell.x + cx[i];
            ny = cell.y + cy[i];
            if ((isempty(a, nx, ny)) && (c = getDegree(a, nx, ny)) < min_deg) {
                min_deg_idx = i;
                min_deg = c;
            }
        }
 
        if (min_deg_idx == -1)
            return null;
 
        nx = cell.x + cx[min_deg_idx];
        ny = cell.y + cy[min_deg_idx];
 
        a[ny * N + nx] = a[(cell.y) * N + (cell.x)] + 1;
        cell.x = nx;
        cell.y = ny;
 
        return cell;
    }
    
    void print(int a[]) {
        for (int i = 0; i < N; ++i) {
            for (int j = 0; j < N; ++j)
                System.out.printf("%d\t", a[j * N + i]);
            System.out.printf("\n");
        }
    }
    
    boolean neighbour(int x, int y, int xx, int yy) {
        for (int i = 0; i < N; ++i)
            if (((x + cx[i]) == xx) &&((y + cy[i]) == yy))
                return true;
        return false;
    }
    
    boolean findClosedTour() {
        int a[] = new int[N * N];
        for (int i = 0; i < N * N; ++i)
            a[i] = -1;
 
        int sx = 3;
        int sy = 2;

        Cell cell = new Cell(sx, sy);
 
        a[cell.y * N + cell.x] = 1;
        Cell ret = null;
        for (int i = 0; i < N * N - 1; ++i)
        {
            ret = nextMove(a, cell);
            if (ret == null)
                return false;
        }
        if (!neighbour(ret.x, ret.y, sx, sy))
            return false;
 
        print(a);
        return true;
    }
    
    public static void main(String[] args)
    {
        while (!new knight_tour().findClosedTour())
        {
            ;
        }
    }
}

标签:return,algorithm,min,Warnsdorff,Knight,++,cell,int,deg
来源: https://blog.csdn.net/weixin_44201353/article/details/119118884

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有