Peg solitaire - 在深度优先搜索中检查钉子与检查孔

时间:2011-11-27 22:31:37

标签: algorithm depth-first-search

我正在尝试用深度优先搜索算法解决Peg Solitaire - 它 应该可以解决自"modern computers can easily examine all game positions in a reasonable time"以来的游戏。即使在23个小时后, 算法没有找到任何解决方案。我做了网络搜索并找到了论文 "Depth-first search solves peg solitaire"。我从论文中尝试了c程序 程序启动后立即找到第一个解决方案。我比较了 算法。算法之间的主要区别在于它们的发现方式 可能的跳跃。虽然我的算法从顶部搜索电路板上的漏洞 从左到右(如有可能,检查每个孔) 跳过),纸张算法从左上角到下方搜索棋盘 对(如果有可能的跳跃,则检查每个挂钩)。两种算法都是 按顺序尝试跳跃。强调差异:

  • 分析漏洞:运行时间23小时无解决方案
  • 分析钉:运行时间10秒,2940解决方案

问题:为什么在如何搜索电路板跳跃方面存在如此巨大的(不可解决的/立即解决的)差异?为什么检查钉子而不是检查孔是否有可能跳跃更好?

您可以使用以下C ++程序尝试该算法。为了保持紧凑,我删除了较不重要的部分(打印电路板,生成初始位板,......)。

#include <iostream>
#include <ctime>
#include <vector>
#include <utility>
#include <ctime>

typedef unsigned __int64 ui64;
typedef std::vector<std::pair<int, int> > vecjumps; // first=from, second=to
ui64 moves = 0;    // Number of moves made so far
int solutions = 0; // Number of solutions found so far
clock_t start;     // To measure time

//          Bitboard
//   Board            Bits         
//  ------------------------------
//    ***           02 03 04      
//    ***           10 11 12      
//  *******   16 17 18 19 20 21 22
//  ***o***   24 25 26 27 28 29 30
//  *******   32 33 34 35 36 37 38
//    ***           42 43 44      
//    ***           50 51 52      
const ui64 bitboard = 0x001c1c7f7f7f1c1c; // 1ULL << 2 | 1ULL << 3 | ...
ui64 board = bitboard & ~(1ULL << 27);    // Initial Board: Bit 27 <=> Hole

// To try the hole-version: Swap Commented and Uncommented parts
vecjumps getMoves(ui64 b)
{
    // Find the possible jumps through bit-shift operations. mr <=> right jump
    // possibilities. The inverted Board represents the Holes. Shifting the
    // board by 16 right/left --> moving all pegs up/down. Shifting the board
    // by 1 --> moving all pegs left/right
    //ui64 mr = (((b >> 1) & b) <<  2) & ~b & bitboard;
    //ui64 md = (((b >> 8) & b) << 16) & ~b & bitboard;
    //ui64 ml = (((b >> 1) & b) >>  1) & ~b & bitboard;
    //ui64 mu = (((b >> 8) & b) >>  8) & ~b & bitboard;
    ui64 mr = ((((b >> 1) & b) <<  2) & ~b & bitboard) >>  2;
    ui64 md = ((((b >> 8) & b) << 16) & ~b & bitboard) >> 16;
    ui64 ml = ((((b >> 1) & b) >>  1) & ~b & bitboard) <<  2;
    ui64 mu = ((((b >> 8) & b) >>  8) & ~b & bitboard) << 16;

    vecjumps jumps;
    jumps.reserve(12);
    for (int i = 2; i < 53; i++)
    {
        //if (mr & (1ULL << i)) jumps.push_back(std::make_pair(i -  2, i));
        //if (md & (1ULL << i)) jumps.push_back(std::make_pair(i - 16, i));
        //if (ml & (1ULL << i)) jumps.push_back(std::make_pair(i +  2, i));
        //if (mu & (1ULL << i)) jumps.push_back(std::make_pair(i + 16, i));
        if (mr & (1ULL << i)) jumps.push_back(std::make_pair(i, i + 2));
        if (md & (1ULL << i)) jumps.push_back(std::make_pair(i, i + 16));
        if (ml & (1ULL << i)) jumps.push_back(std::make_pair(i, i - 2));
        if (mu & (1ULL << i)) jumps.push_back(std::make_pair(i, i - 16));
    }
    return jumps;
}

void makeMove(ui64& b, int from, int to)
{
    // Through a xor-instruction, a jump from 11 to 27 includes 19
    // 19 = (11 + 27) / 2
    b ^= 1ULL << from | 1ULL << (from + to) / 2 | 1ULL << to;
    moves++;
    if (moves % 10000000 == 0)
        printf("(%8d, %14llu moves, %lf)\n", 
            solutions, moves, (double)(clock() - start) / CLOCKS_PER_SEC);
}

// Depth First Search Algorithm
bool findSolution(int depth)
{
    if (!depth) return ((1ULL << 27) & board);
    vecjumps jumps = getMoves(board);
    for (vecjumps::const_iterator cit = jumps.begin(); cit != jumps.end();
         ++cit)
    {
        ui64 copy = board;
        makeMove(board, (*cit).first, (*cit).second);
        if (findSolution(depth - 1)) solutions++;
        board = copy;
    }
    return false;
}

int main()
{
    start = clock();
    findSolution(31);   
    printf("(%8d, %14llu moves, %lf)\n", 
        solutions, moves, (double)(clock() - start) / CLOCKS_PER_SEC);
    return 0;
}

1 个答案:

答案 0 :(得分:1)

如果在任一方法中结果树中没有循环,并且结果树相同,则在使用相同搜索算法时,hudge差异的原因必须是节点展开的顺序(启发式)。我还在检查你的实现,但一切似乎都正确,所以我看不出速度差异的任何其他原因。

前段时间我对这个问题有了一个分析,我在书签上找到了这个:你可以阅读更多信息,深度搜索与广度搜索以及一些启发式方法来改善搜索:http://www.durangobill.com/Peg33.html < / p>