分析:如图所示,一共有15个洞,其中一个空着,剩下的洞里各有一个小球。每次可以让一个小球越过同一条直线上的一个或多个连续的小球,落到最近的空洞(不能越过空洞),然后拿走被跳过的小球。例如,让14调到空洞5中,则洞9里的小球会被拿走,因此操作之后洞9和14会变空,而5里面会有一个小球。你的任务是用最少的步数让整个棋盘只剩下一个小球,并且位于初始时的那个空洞中。(本段摘自《算法竞赛入门经典(第2版)》)
分析:
使用迭代加深搜索,事先在常量数组里存好可以跳的地方和会经过的棋子。处理起来方便一点。
代码:
#include <iostream>
#include <algorithm>
#include <fstream>
#include <string>
#include <cstring>
#include <vector>
#include <queue>
#include <cmath>
#include <cctype>
#include <stack>
#include <set>
using namespace std;
const int maxn = 15 + 5, INF = 10;
const int z[16][6] = {
{},
{ 4, 6, 7,10,11,15},
{ 7, 9,11,14},
{ 8,10,12,15},
{ 1, 6,11,13},
{12,14},
{ 1, 4,13,15},
{ 1, 2, 9,10},
{ 3,10},
{ 2, 7},
{ 1, 3, 7, 8},
{ 1, 2, 4, 13,14,15},
{ 3, 5,14,15},
{ 4, 6,11,15},
{ 2, 5,11,12},
{ 1, 3, 6,11,12,13}
};
const int WAY[100][3] = {
{ 1, 4, 2},{ 1, 6, 3},{ 1, 7, 2},{ 1, 7, 4},{ 1,10, 3},{ 1,10, 6},{ 1,11, 2},{ 1,11, 4},{ 1,11, 7},{ 1,15, 3},{ 1,15, 6},{ 1,15,10},
{ 2, 7, 4},{ 2, 9, 5},{ 2,11, 4},{ 2,11, 7},{ 2,14, 5},{ 2,14, 9},
{ 3, 8, 5},{ 3,10, 6},{ 3,12, 5},{ 3,12, 8},{ 3,15, 6},{ 3,15,10},
{ 4, 1, 2},{ 4, 6, 5},{ 4,11, 7},{ 4,13, 8},
{ 5,12, 8},{ 5,14,9},
{ 6, 1, 3},{ 6, 4, 5},{ 6,13, 9},{6, 15,10},
{ 7, 1, 2},{ 7, 1, 4},{ 7, 2, 4},{ 7, 9, 8},{ 7,10, 8},{ 7,10, 9},
{ 8, 3, 5},{ 8,10, 9},
{ 9, 2, 5},{ 9, 7, 8},
{10, 1, 3},{10, 1, 6},{10, 3, 6},{10, 7, 8},{10, 7, 9},{10, 8, 9},
{11, 1, 2},{11, 1, 4},{11, 1, 7},{11, 2, 4},{11, 2, 7},{11, 4, 7},{11,13,12},{11,14,12},{11,14,13},{11,15,12},{11,15,13},{11,15,14},
{12, 3, 5},{12, 3, 8},{12, 5, 8},{12,14,13},{12,15,13},{12,15,14},
{13, 4, 8},{13, 6, 9},{13,11,12},{13,15,14},
{14, 2, 5},{14, 2, 9},{14, 5, 9},{14,11,12},{14,11,13},{14,12,13},
{15, 1, 3},{15, 1, 6},{15, 1,10},{15, 3, 6},{15, 3,10},{15, 6,10},{15,11,12},{15,11,13},{15,11,14},{15,12,13},{15,12,14},{15,13,14}
};
int T, x;
int v[maxn], path[maxn][2];
vector< int > vec[maxn];
vector< int > way[maxn][maxn];
void init()
{
for (int i = 1; i <= 15; ++i)
{
for (int j = 0; j < 6; ++j)
if (z[i][j])
vec[i].push_back(z[i][j]);
}
for (int i = 0; i < 100; ++i)
way[WAY[i][0]][WAY[i][1]].push_back(WAY[i][2]);
}
bool judge()
{
for (int i = 1; i <= 15; ++i)
if ((i == x && !v[i]) || (i != x && v[i]))
return false;
return true;
}
bool jump(int x, int y)
{
for (int i = 0; i < way[x][y].size(); ++i)
if (!v[way[x][y][i]])
return false;
return true;
}
void remove(int x, int y)
{
for (int i = 0; i < way[x][y].size(); ++i)
v[way[x][y][i]] = 0;
v[x] = 0;
v[y] = 1;
}
void recover(int x, int y)
{
for (int i = 0; i < way[x][y].size(); ++i)
v[way[x][y][i]] = 1;
v[x] = 1;
v[y] = 0;
}
bool DFS(int deep, int limit)
{
if (deep == limit)
{
if (judge())
{
printf("%d\n", limit);
for (int i = 0; i < limit; ++i)
if (i < limit - 1)
printf("%d %d ", path[i][0], path[i][1]);
else
printf("%d %d\n", path[i][0], path[i][1]);
return true;
}
return false;
}
for (int i = 1; i <= 15; ++i)
{
if (v[i])
{
for (int j = 0; j < vec[i].size(); ++j)
{
int u = vec[i][j];
if (!v[u] && jump(i, u))
{
remove(i, u);
path[deep][0] = i;
path[deep][1] = u;
if (DFS(deep + 1, limit))
return true;
recover(i, u);
}
}
}
}
return false;
}
int main()
{
init();
scanf("%d", &T);
for (int C = 0; C < T; ++C)
{
scanf("%d", &x);
for (int i = 1; i <= 15; ++i)
if (i == x)
v[i] = 0;
else
v[i] = 1;
for (int maxd = 1; ; ++maxd)
if (DFS(0, maxd))
break;
}
return 0;
}