比吕震宇的慢多了,我的Intel N100上0.624s,他的兆芯KX-6640MA上0.314秒。
写都写了,贴出来吧:

#include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <unordered_set> using std::unordered_set; typedef unsigned char byte;const char* NM[] = { "曹", "关", "张", "黄", "赵", "马", "丁", "丙", "乙", "甲" }; int W[] = { 2, 2, 2, 2, 2, 2, 1, 1, 1, 1 }; int H[] = { 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; const int D[4][2] = { 0, -1, 0, 1, -1, 0, 1, 0 };enum { QMAX = 36 * 1000 * 1000 }; struct State {uint64_t xys; // xy坐标们byte b[5][4];int p; // 局面路径的previous// int next; // Hash表里的nextvoid clear () { xys = 0; memset(b, 0, sizeof(b)); }State& operator= (int a[10][2]);void toary(int a[10][2]);void operator= (const char* s);void print(const char* s = "");bool _can_move (int a[10][2], int i, int j);bool can_move (int a[10][2], int i, int j); } states[QMAX + 40]; int qh, qt = 1; // queue head, tail unordered_set<uint64_t> seen; // 改Hash表,和states二合一 State& State::operator= (int a[10][2]) {for (int i = 0; i < 10; i++) {const uint64_t x = a[i][0], y = a[i][1];xys |= ((x << 3) | y) << (i * 5); // gcc不-O都会换成<<2再+1for (int yy = y; yy < y + H[i]; yy++)for (int xx = x; xx < x + W[i]; xx++)b[yy][xx] = 1;}return *this; }void State::toary (int a[10][2]) {for (int i = 0; i < 10; i++) {int xy = xys >> (i * 5);a[i][0] = (xy >> 3) & 3; // xa[i][1] = xy & 7; // y } }void State::operator= (const char* s) {int a[10][2] = {}, g = 1, p = 6;for (int x = 3; x >= 0; x--)for (int y = 4; y >= 0; y--) {#define CASE(c, i) case c: a[i][0] = x; a[i][1] = y; break;switch (s[x * 5 + y]) {CASE('c', 0) CASE('g', 1) // 曹关CASE('z', 2) CASE('h', 3) // 张黄CASE('l', 4) CASE('m', 5) // 子龙(l) 马case 'p': a[p][0] = x; a[p++][1] = y;}}static const char* S[] = { "gg", "zz", "hh", "ll", "mm" };for (int i = 0; i < 5; i++)if (strstr(s, S[i])) W[i+1] = 1, H[i+1] = 2;*this = a; }void State::print (const char* s) {const char* b[5][4] = {};int a[10][2]; toary(a);for (int i = 0; i < 10; i++) {int x = a[i][0], y = a[i][1];for (int yy = y; yy < y + H[i]; yy++)for (int xx = x; xx < x + W[i]; xx++)b[yy][xx] = NM[i];}for (int y = 0; y < 5; y++) {for (int x = 0; x < 4; x++) printf("%s", b[y][x] ? : " ");puts("");}printf("%s\n", s); }bool State::can_move (int a[10][2], int i, int j) {int ox = a[i][0], oy = a[i][1];bool ok = _can_move(a, i, j);char s[256];sprintf(s, "%s: %d,%d -> %d,%d %s", NM[i], ox, oy, a[i][0], a[i][1], ok ? "OK" : "");print(s); getchar();return ok; }bool State::_can_move (int a[10][2], int i, int j) {const int ox = a[i][0], oy = a[i][1];int x = (a[i][0] += D[j][0]), y = (a[i][1] += D[j][1]);if (x < 0 || x + W[i] > 4 || y < 0 || y + H[i] > 5) return false;//D[4][2] = { 0,-1, 0,1, -1,0, 1,0 };if (j == 0) {for (int w = 0; w < W[i]; w++) if (b[y][x + w]) return false;return true;}else if (j == 1) {y = oy + H[i];for (int w = 0; w < W[i]; w++) if (b[y][x + w]) return false;return true;}else if (j == 2) {for (int h = 0; h < H[i]; h++) if (b[y + h][x]) return false;return true;}else {x = ox + W[i];for (int h = 0; h < H[i]; h++) if (b[y + h][x]) return false;return true;} }void print_path () {// 用数组存放的单链表就地翻转int prev = -1, next = -1;for (int cur = qh; cur != -1;) {next = states[cur].p;states[cur].p = prev;prev = cur; cur = next;}int n = 0;for (int p = 0; p != -1; p = states[p].p) {// states[p].print();++n;}printf("%d\n", n); }int main () {//states[0] = "pp zz""ccghh""ccgll""pp mm";states[0] = "pzzpg""cc g""ccllm""phhpm";states[0].print();states[0].p = -1;seen.insert(states[0].xys);for (; qh < qt; qh++) {int a[10][2]; states[qh].toary(a);if (a[0][1] == 3) { print_path(); break; }for (int i = 0; i < 10; i++)for (int j = 0; j < 4; j++) {if (states[qh]._can_move(a, i, j)) {states[qt] = a;if (seen.find(states[qt].xys) == seen.end()) {seen.insert(states[qt].xys);states[qt++].p = qh;}else states[qt].clear();}a[i][0] -= D[j][0]; a[i][1] -= D[j][1];}}printf("%d\n", qt);return 0; }