【问题描述】

Mayan puzzle是最近流行起来的一个游戏。游戏界面是一个 7 行5 列的棋盘,上面堆放

着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上。游

戏通关是指在规定的步数内消除所有的方块,消除方块的规则如下:

1 、 每步移动可以且仅可以沿横向(即向左或向右)拖动某一方块一格:当拖动这一方

块时,如果拖动后到达的位置(以下称目标位置)也有方块,那么这两个方块将交换位置(参

见输入输出样例说明中的图6 到图7 );如果目标位置上没有方块,那么被拖动的方块将从

原来的竖列中抽出,并从目标位置上掉落(直到不悬空,参见下面图1 和图2 );

2 、 任一时刻,如果在一横行或者竖列上有连续三个或者三个以上相同颜色的方块,则

它们将立即被消除(参见图1 到图3)。

注意:

a) 如果同时有多组方块满足消除条件,几组方块会同时被消除(例如下面图4 ,三个颜

色为1 的方块和三个颜色为 2 的方块会同时被消除,最后剩下一个颜色为 2 的方块)。

b) 当出现行和列都满足消除条件且行列共享某个方块时,行和列上满足消除条件的所

有方块会被同时消除(例如下面图5 所示的情形,5 个方块会同时被消除)。

3 、 方块消除之后,消除位置之上的方块将掉落,掉落后可能会引起新的方块消除。注

意:掉落的过程中将不会有方块的消除。

上面图1 到图 3 给出了在棋盘上移动一块方块之后棋盘的变化。棋盘的左下角方块的坐

标为(0, 0 ),将位于(3, 3 )的方块向左移动之后,游戏界面从图 1 变成图 2 所示的状态,

此时在一竖列上有连续三块颜色为4 的方块,满足消除条件,消除连续3 块颜色为4 的方块

后,上方的颜色为3 的方块掉落,形成图 3 所示的局面。

【输入】

输入文件mayan.in,共 6 行。

第一行为一个正整数n ,表示要求游戏通关的步数。

接下来的5 行,描述 7*5 的游戏界面。每行若干个整数,每两个整数之间用一个空格隔

开,每行以一个0 结束,自下向上表示每竖列方块的颜色编号(颜色不多于10种,从1 开

始顺序编号,相同数字表示相同颜色)。

输入数据保证初始棋盘中没有可以消除的方块。

【输出】

输出文件名为mayan.out。

如果有解决方案,输出 n 行,每行包含 3 个整数x,y,g ,表示一次移动,每两个整数

之间用一个空格隔开,其中(x ,y)表示要移动的方块的坐标,g 表示移动的方向,1 表示

向右移动,-1表示向左移动。注意:多组解时,按照 x 为第一关健字,y 为第二关健字,1

优先于-1 ,给出一组字典序最小的解。游戏界面左下角的坐标为(0 ,0 )。

如果没有解决方案,输出一行,包含一个整数-1。

【输入输出样例】

mayan.in

3

1 0

2 1 0

2 3 4 0

3 1 0

2 4 3 4 0

mayan.out

2 1 1

3 1 1

3 0 1

【输入输出样例说明】

按箭头方向的顺序分别为图6 到图11

样例输入的游戏局面如上面第一个图片所示,依次移动的三步是:(2 ,1 )处的方格向
右移动,(3,1 )处的方格向右移动,(3 ,0)处的方格向右移动,最后可以将棋盘上所有方
块消除。 
【数据范围】 
对于30% 的数据,初始棋盘上的方块都在棋盘的最下面一行; 
对于100%的数据,0 < n≤5 。

【题解】

这是一道搜索题。

这么长的题。爆搜肯定能过啦。。

说一下搜索的策略。

就是for一遍所有的有砖块的位置。

对每一个砖块都进行尝试即可。

但是还是有一些技巧的。

第一:

如果当前这个砖块的左边是空的,则可以往左边移动一格。但如果左边也是砖块,那么久不移动。

第二:

除了第一种要移动的情况外。都只往右边移动。因为向左的情况会发生重复的。

就这两种。。

最难的还是消除和下落的过程。

消除的话。同样按照顺序for一遍所有的砖块。

对于所有的砖块

向下数3个如果都是同样颜色,先标记为可消除,即先不消除。然后向右数3个如果也是同样颜色。那么也标记为可消除,同样先不消除。

然后最后再for一遍所有的砖块。把那些被标记的砖块置为空。

如果能进行消除。那么就一定要进行一次下落操作;

下落操作:

for (int i = 1; i <= 5;i++)

for (int j = 2;j <= 7;j++) //如果在高度为1处则不可能需要下落

if (a[i][j] > 0 && a[i][j] == 0) //如果下面一格为空,则肯定要进行下落操作。

则令k=j-1,然后一直递减k,直到找到一个k满足a[i][k] == 0,a[i][k-1] > 0;特殊的,我们认为a[i][0]是一个大于0的数字。

然后让a[i][k] = a[i][j];a[i][j] = 0即可。这样就完成了把一个悬空的砖块往下降的过程。

很多人可能觉得这样一个一个降太麻烦了。但是如果一堆一堆地降,会需要另外一个变量。来获取这个砖块上面的砖块的信息。然后还有一堆一堆地赋值,以模拟往下降的过程。想想就可怕。还是一个砖块一个砖块往下降比较简单。写程序就是如此。不要按照我们脑子中呈现的过程来写。脑子可能处理得很好。但是实际操作起来就不一定那么容易了。这样两层for循环是的确可以处理所有的下落问题的。

最后记得记录一下方案即可。

另外,可能有人觉得之前出现过相同位置进行过了操作就不需要进行了。这里有可能会出现,上一次在这个位置操作过后,整个局面发生了大的变化。而再在同样的位置操作,就可能出现全部消除的情况。所以不能轻易地跳过某一个位置。

最后有一个快速判断一定无解的方法。

就是把所有的颜色统计一下。如果有一种颜色的砖块数目<3则一定无解。

当然只能快速排除这种情况。

【代码】

#include <cstdio>
#include <stdlib.h> int n,a[6][8] = {0},fa[6][4] ={0}; //a用于存储初始状态,fa则是方案,1,2维是坐标3是方向 void special_judge() //这里进行一次 特判 即某种颜色的砖块数目是否小于3
{
int c[11] = {0};
for (int i = 1;i <= 5;i++)
for (int j = 1;j <=7;j++)
c[a[i][j]]++; //统计颜色 题目有说最多10种颜色
for (int i = 1;i <= 10;i++)
if (c[i] >0 ) //一定要是出现过的颜色
{
if (c[i] < 3) //如果小于3则输出无解
{
printf("-1");
exit(0);
}
}
} void input_data() //输入数据
{
scanf("%d",&n);
for (int i =1;i <= 5;i++ //5列)
{
int x,j=0;
scanf("%d",&x);
while (x!=0) //转换成1-7而不是0-6这样处理方便点。符合人的思维。
{
j++;
a[i][j] = x;
scanf("%d",&x);
}
}
} bool xiaochu() //这是消除过程
{
bool flag = false;
bool aa[6][8] = {0};
for (int i = 1;i <= 5;i++)
for (int j = 1;j <= 7;j++) //我有说。先标记哪些格子是可以消除的
{ //竖着3个
if (a[i][j] >0 && j+2<=7 && a[i][j] == a[i][j+1] && a[i][j+1] == a[i][j+2])
for (int k = j;k<=j+2;k++)
aa[i][k] = true;
//横着3个的情况
if (a[i][j] >0 && i+2<=5 && a[i][j] == a[i+1][j] && a[i+1][j] == a[i+2][j])
for (int k = i;k<=i+2;k++)
aa[k][j] = true;
}
for (int i = 1;i <= 5;i++)
for (int j = 1;j <= 7;j++) //最后看一下哪一些格子是可以消除的。
if (aa[i][j])
{
a[i][j] = 0;
flag = true; //如果有一个可以消除 就说明有进行消除工作 为是否继续下落提供参考
}
return flag;
} void xialuo() //下落的过程
{
for (int i = 1;i <= 5;i++)
for (int j = 2;j <= 7;j++) //因为是一个一个往下落的过程
{ //所以要枚举每一个砖块
if (a[i][j] > 0 && a[i][j-1] == 0) //如果这个砖块下面是空的
{
int k = j-1; //寻找它会下落到哪一个位置
while (k>0 && a[i][k-1] == 0) k--;
if (k==0)
k = 1;
a[i][k] = a[i][j]; //将它下落到这个位置
a[i][j] = 0; //原位置记为空
}
}
} void fuzhi(int a[6][8],int b[6][8]) //把b数组赋值给a数组
{ //不能写成a[][] 和 b[][] ,要具体地把里面是几维的写上去
for (int i = 1;i <= 5;i++)
for (int j = 1;j <= 7;j++)
a[i][j] = b[i][j];
} bool success()//判断是否整个游戏中都没有了砖块
{
for (int i = 1;i <= 5;i++)
for (int j =1; j<= 7;j++)
if (a[i][j]!=0)
return false; //如果有一个砖块就返回false表示没有成功
return true;
} void sear_ch(int k)
{
int temp[6][8];
if (k > n) //等同于 k==n+1
{
if (success()) //如果成功消除掉所有的砖块
{
for (int i = 1;i <= n;i++)
printf("%d %d %d\n",fa[i][1]-1,fa[i][2]-1,fa[i][3]); //输出方案
//因为我们在处理的时候从1开始,所以坐标都要减去1
exit(0); //表示结束所有程序不再执行任何代码
}
return;
}
for (int i = 1;i <= 5;i++)
for (int j = 1;j<=7;j++)
if (a[i][j] >0) //枚举每一个砖块
{ fuzhi(temp,a); //用来回溯。先把a赋值给temp,然后我们对a进行操作,
//这个状态搜完后再把temp赋值给a
if ( i > 1 && (a[i-1][j] == 0)) //如果左边没有越界且左边是一个空的地方
{
int t = a[i-1][j];
a[i-1][j] = a[i][j];
a[i][j] = t; //和左边的位置交换一下
xialuo();//先执行下落过程
while (xiaochu() == true) //然后开始消除
//能消除就继续下落然后再尝试消除(一定要给过程名加括号,不然不会执行!)
xialuo();
fa[k][1] = i;
fa[k][2] = j;
fa[k][3] = -1;//记录下这一步的方案是什么
sear_ch(k+1); //然后搜索下一步
fuzhi(a,temp);//回溯
}
if (i < 5 && a[i+1][j]!=a[i][j]) //这是向右移动的过程。
{
int tt = a[i][j]; //右边不管是什么都移动(如果可以)
a[i][j] = a[i+1][j];
a[i+1][j] = tt;
xialuo(); //移动后先下落
while (xiaochu() == true) //然后再尝试消除和下落的过程
xialuo();
fa[k][1] = i;
fa[k][2] = j;
fa[k][3] = 1; //记录下这一步的方案
sear_ch(k+1);
fuzhi(a,temp); //回溯
}
} } int main()
{
//freopen("F:\\rush.txt","r",stdin);
input_data();
special_judge();
sear_ch(1);
printf("-1");//如果搜索完还没找到就输出无解信息。
return 0;
}

【z03】Mayan游戏的更多相关文章

  1. NOIP2011 Mayan游戏

    3 Mayan游戏 题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上 ...

  2. noip提高组2011 Mayan游戏

    Mayan游戏 描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个7行5列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.**游戏通关 ...

  3. [题目] Luogu P1312 Mayan游戏

    题面 题目描述 $ Mayan puzzle $是最近流行起来的一个游戏.游戏界面是一个 \(7行 \times 5列\)的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放 ...

  4. $Mayan$游戏

    \(Mayan\)游戏 好啊,一年(半年)来的梦魇,终于结束了. 其实我从来没料到整体竟然会如此暴力--做的时候机房里冷得很,感觉晕晕乎乎地做完了,晕晕乎乎地调了好久,晕晕乎乎地听(看了题解的)\(q ...

  5. 洛谷P1312 Mayan游戏

    P1312 Mayan游戏 题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他 ...

  6. [Luogu 1312] noip11 Mayan游戏

    [Luogu 1312] noip11 Mayan游戏 Problem: Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即 ...

  7. luoguP1312 Mayan游戏 题解(NOIP2011)

    luoguP1312 Mayan游戏 题目 #include<bits/stdc++.h> #define ll long long #define rg register #define ...

  8. Luogu P1312 Mayan游戏(搜索)

    P1312 Mayan游戏 题意 题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个\(7\)行\(\times 5\)列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必 ...

  9. 洛谷P1312 [NOIP2011提高组Day1T3]Mayan游戏

    Mayan游戏 题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.游 ...

随机推荐

  1. vue实现多语言国际化(vue-i18n),结合element ui、vue-router、echarts以及joint等。

    老板说我们的项目要和国际接轨,于是乎,加上了多语言(vue-i18n).项目用到的UI框架是element ui ,后续echarts.joint等全都得加上多语言. 一.言归正传,i18n在vue项 ...

  2. tcl -mode

    -exact     严格匹配(如string equal) -glob 通配符式匹配(string match) -regexp   正则表达式匹配(regexp) array get和array ...

  3. jemter--录制的脚本设置循环次数不起作用

    以下是比较jmeter线程组中设置循环次数和循环控制器中设置循环次数的区别 1.jmeter生成的脚本没有step1(循环控制器)控制器,故循环在线程组中设置   2.badboy录制的脚本有setp ...

  4. BAT面试常的问题和最佳答案

    原标题:BAT面试常的问题和最佳答案 技术面试 1.servlet执行流程 客户端发出http请求,web服务器将请求转发到servlet容器,servlet容器解析url并根据web.xml找到相对 ...

  5. (转)const char to LPCTSTR不能转化问题

    转: const char to LPCTSTR不能转化问题 Visual C++ 2008里cannot convert parameter 1 from 'const char [13]' to ...

  6. [Nuxt] Display Vuex Data Differently in Each Page of Nuxt and Vue.js

    You often use the same data in different ways across pages. This lesson walks you through setting up ...

  7. stm32的复用与映射

    摘自:https://blog.csdn.net/lincheng15/article/details/51789093 摘自:http://www.51hei.com/bbs/dpj-36242-1 ...

  8. 6、USB Video Class Specification

    关于USB Class 将设备归为既定的类别,并对相应类别的设备的在USB协议的应用级协议和接口作出规范,这样只要按照类设备的标准实现驱动程序和设备,则一套驱动可以驱动这一类的所有设备,而这一类设备可 ...

  9. 魔兽争霸war3心得体会(一):UD的冰甲蜘蛛流

    玩war3好几年了,之前都是打打电脑,随便玩玩的.刚刚在浩方等平台上和人玩的时候,各种被虐,很难赢一局.从去年开始,才认真玩.思考下各种战术. 最初,使用的是兽族orc,后来觉得兽族不够厉害,玩到对战 ...

  10. 【u243】拓扑排序

    Time Limit: 1 second Memory Limit: 128 MB [问题描述] 一些历史迷们打算把历史上的一些大事件按时间顺序列出来.但是,由于资料不全,每个事件发生的具体时间都没有 ...