目录
移箱迷宫
规则:

补充规则:
每次滑动,相当于是盒子和四邻居之一交换位置,这个邻居可能是空格也可能是盒子,交换位置之后所有格子往下掉落。
如果形成3个以上,也会一次性全部消除。
如果多个方向同时形成3个或以上,也会一次性全部消除。
消除之后,剩下的盒子会往下掉落,如果形成新的可消除组合,则自动继续消除。
初级
(11)

首先寻找匹配方向:

然后寻找优先消除块:

最后找到操作方法:

(15)

首先寻找匹配方向:

然后寻找优先消除块:

我画了3个黑框,因为左边2个块和上边1个块距离太远,所以在消除这3个块之前还要先把右边的6个块消除掉。
最后找到操作方法:

(23)

这里的匹配结果是蓝色格子往左移2步,所以操作方法就是:

(24)


(27)


(30)


(33)


(39)


(40)


(42)

首先,红色和深蓝色的水平坐标是OK的,即只要往下掉到同一行即可消除,而黄色是左边的格子需要往右移动一步。
基于此,比较容易想到一个三步的操作方法:


根据这个方案,可以想到一个步骤更少的方案:

(45)
参考下文《递归搜索》
(49)


策略一:纵向匹配法
首先寻找匹配方向,然后寻找优先消除块,最后找到操作方法。
参考初级关卡(11)和(15)
策略二:横向匹配法
如果寻找到的匹配方向是把某个单个的箱子横着移动,则直接得到对应数量的操作内容。
参考初级关卡(23)
策略三:基于移动方格的方案简化
有时我们拿到一个操作数比较多的方案,可以分析我们的整体操作是把哪些方格移动了,移到了什么位置,基于这个操作结果可以反推出一个操作数更少的操作方案。
参考初级关卡(42)
递归搜索
我们把不同的颜色用正整数区分,0表示空格,然后用递归搜索即可搜出一个解。
注意,我们在框定尺寸时,要往左右两边留出空列,而最上面是不需要留出空行的。
代码:
bool down(vector<vector<int>>&v)
{
bool flag = false;
int row = v.size(), col = v[0].size();
for (int j = 0; j < col; j++) {
int low = 0;
for (int i = 1; i < row; i++) {
if (v[low][j] == 0) {
if (v[i][j])low = i;
}
else {
if (v[i][j])continue;
for (int k = i; k>low; k--) {
v[k][j] = v[k - 1][j];
}
v[low][j] = 0;
flag = true;
low++;
}
}
}
return flag;
}
bool dels(vector<vector<int>>& v)
{
int row = v.size(), col = v[0].size();
vector<vector<bool>>canDel(row, vector<bool>(col, false));
for (int i = 0; i < row; i++) {
for (int j = 2; j < col; j++) {
if (v[i][j] && v[i][j - 2] == v[i][j] && v[i][j - 1] == v[i][j]) {
canDel[i][j - 2] = canDel[i][j - 1] = canDel[i][j] = true;
}
}
}
for (int i = 2; i < row; i++) {
for (int j = 0; j < col; j++) {
if (v[i][j] && v[i-2][j] == v[i][j] && v[i-1][j] == v[i][j]) {
canDel[i-2][j] = canDel[i-1][j] = canDel[i][j] = true;
}
}
}
bool flag = false;
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (canDel[i][j]) {
flag = true, v[i][j] = 0;
}
}
}
return flag;
}
void downAndDel(vector<vector<int>>& v)
{
while (down(v) || dels(v));
}
bool isFinish(const vector<vector<int>>& v)
{
int row = v.size(), col = v[0].size();
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (v[i][j]) return false;
}
}
return true;
}
bool search(vector<vector<int>> v, int n)
{
if (!n)return isFinish(v);
int row = v.size(), col = v[0].size();
for (int i = 0; i < row; i++) {
for (int j = 1; j < col; j++) {
if (v[i][j] == v[i][j - 1])continue;
auto v2 = v;
v[i][j] ^= v[i][j - 1] ^= v[i][j] ^= v[i][j - 1];
downAndDel(v);
if (search(v, n-1)) {
cout << i << " " << j << " " << i << " " << j - 1 << endl;
return true;
}
v = v2;
}
}
for (int i = 1; i < row; i++) {
for (int j = 0; j < col; j++) {
if (v[i][j] == v[i-1][j])continue;
auto v2 = v;
v[i][j] ^= v[i - 1][j] ^= v[i][j] ^= v[i - 1][j];
downAndDel(v);
if (search(v, n - 1)) {
cout << i << " " << j << " " << i-1 << " " << j << endl;
return true;
}
v = v2;
}
}
return false;
}
以初级关卡(45)为例:

所以调用代码就是:
int main()
{
vector<vector<int>>v{
{0,1,0,0,0,0},
{0,2,0,0,0,0},
{0,3,0,0,0,0},
{0,2,1,0,0,0},
{0,1,3,3,0,0},
{0,2,2,1,0,0},
{0,1,1,2,2,0}
};
search(v, 2);
return 0;
}
运行结果:
4 1 4 0
3 1 2 1
从下往上,先把(3,1)和(2,1)互换,再把(4,1)和(4,0)互换
即:

策略四:难以分割的相邻同色块
在上面的初级关卡(45)中,其实很容易想到红色的块往左推的操作,但是如果第一步就这样操作就会造成四个黄色块(最下面一行2个,倒数第二行2个)一起消除,从而无解。
我的思路一直是如何分割倒数第二行的2个黄色块,一直没想过可以让这6个黄色块同时消除。
所以策略四就是,如果遇到难以分割的相邻同色块,考虑不分割,而是两组同时消除。
中级
(2)

这一关的关键是4个黄的要一起消除,4个深蓝的也要一起消除。

星云穿越
最强大脑同款项目。
两对残局





三对残局
1号

2步转化成2号
2号

2步转化成3号
3号

4号

2步就全挨着了
5号

1步就全挨着了
6号

2步变成7号
7号

2步把不挨着的(左下和右上)消了,剩下2对挨着的
8号

2步就全挨着了
9号

2步就全挨着了
10号

3步(左上左)变成11号
11号

1步就全挨着了
12号

2步变成13号
13号

2步变成14号
14号

2步把橙色的(第一列和最后一列)消掉
15号

2步变成16号
16号

1步就全挨着了
简单(4对)


中级(6对)


高级(7对)



困难(8对)





移箱迷宫、星云穿越&spm=1001.2101.3001.5002&articleId=159967898&d=1&t=3&u=bb3f97319f7943e289580b7b0b590b44)
992

被折叠的 条评论
为什么被折叠?



