描述
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所示的局面。
格式
输入格式
第一行为一个正整数n,表示要求游戏关的步数。
接下来的5行,描述7*5的游戏界面。每行若干个整数,每两个整数之间用一个空格隔开,每行以一个0 结束,自下向上表示每竖列方块的颜色编号(颜色不多于10种,从1开始顺序编号,相同数字表示相同颜色)。
输入数据保证初始棋盘中没有可以消除的方块。
输出格式
如果有解决方案,输出n行,每行包含3个整数x,y,g,表示一次移动,每两个整数之间用一个空格隔开,其中(x,y)表示要移动的方块的坐标,g表示移动的方向,1表示向右移动,-1表示向左移动。注意:多组解时,按照x为第一关键字,y为第二关键字,1优先于-1,给出一组字典序最小的解。游戏界面左下角的坐标为(0, 0)。
如果没有解决方案,输出一行,包含一个整数-1。
样例1
样例输入1[复制]
3 1 0 2 1 0 2 3 4 0 3 1 0 2 4 3 4 0
样例输出1[复制]
2 1 1 3 1 1 3 0 1
限制
3s
提示
样例输入的游戏局面如图6到图11所示。依次移动的三步是:(2,1)处的方格向右移动,(3,1)处的方格向右移动,(3,0)处的方格向右移动,最后可以将棋盘上所有方块消除。
数据规模如下:
对于30%的数据,初始棋盘上的方块都在棋盘的最下面一行;
对于100%的数据,0 < n ≤ 5。
在做题时应注意:
(1)不用枚举整个棋盘,只需要每列都搜索到最高层即可。
(2)我们发现把(x,y)向右移和把(x+1,y)向左移是一样的,不用重复搜索,所以我们可以只向右交换,此外还应注意到空格不能移动,所以要判断这种特殊情况。
(3)应注意到可能出现以下状况:
即出现十字型。
(4)为了提高效率,防止一个点被算不止一次,所以要等到全部搜索完再统一消去。
(5)注意左右移动时要先判断是否下落。
先来一个30分的做法 :
program mayan;
type
armap=array[0..7,0..5] of longint;
tnode=record
end;
var
n:longint;//步数
map:armap;
procedure init;
begin
assign(input,‘mayan.in‘);
assign(output,‘mayan.out‘);
reset(input);
rewrite(output);
end;procedure outit;
begin
close(input);
close(output);
halt;
end;
procedure readdata;
var
i,num,x:longint;
begin
read(n);
num:=0;
for i:=1 to 5 do
begin
read(x);
while x<>0 do
begin
inc(num);
map[num,i]:=x;
read(x);
end;
num:=0;
end;
{ for i:=1 to 7 do
begin
for x:=1 to 5 do
if map[i,x]=0 then write(‘ ‘)
else write(map[i,x],‘ ‘);
writeln;
end;}
end;
procedure percent30;
var
i:longint;
flag:longint;
num:longint;
k:array[1..3] of longint;//记录flag=3时的颜色状态
begin
flag:=0;
for i:=1 to 5 do
if map[1,i]<>0 then
inc(flag);//flag为1,2,4和5时必定无法消完
if flag in [1,2,4,5] then
begin
writeln(-1);
outit;
end;
//处理剩下flag=3的情况
num:=0;
for i:=1 to 5 do
if map[1,i]<>0 then
begin
inc(num);
k[num]:=map[1,i];
end;
if not((k[1]=k[2])or(k[2]=k[3])or(k[1]=k[3])) then
begin
writeln(-1);
outit;
end;
//剩下只有第一行有三个并且颜色相同 且要在刚好steps步数下完成
//(由于初始状态无可消除的 所以只有三种情况 打表。。。)
for i:=1 to 5 do if map[1,i]<>0 then map[1,i]:=1 else map[1,i]:=0;//把有颜色的处理成1
//三种情况分别为1 1 0 1 0 1 1 0 0 1 1 0 1 0 1
if (map[1,1]=1)and(map[1,2]=1)and(map[1,3]=0)and(map[1,4]=1)and(map[1,5]=0) then
begin//1 1 0 1 0
if n=1 then
begin
writeln(‘3 0 -1‘);
outit;
end
else if n=2 then
begin
writeln(‘1 0 1‘);
writeln(‘0 0 1‘);
outit;
end
else if n=4 then
begin
writeln(‘3 0 1‘);
writeln(‘1 0 1‘);
writeln(‘0 0 1‘);
writeln(‘1 0 1‘);
outit;
end
else begin
writeln(-1);
outit;
end;
end
else if (map[1,1]=1)and(map[1,2]=1)and(map[1,3]=0)and(map[1,4]=0)and(map[1,5]=1) then
begin//1 1 0 0 1
if n=2 then
begin
writeln(‘4 0 -1‘);
writeln(‘3 0 -1‘);
outit;
end
else if n=3 then
begin
writeln(‘1 0 1‘);
writeln(‘0 0 1‘);
writeln(‘4 0 -1‘);
outit;
end
else if n=4 then
begin
writeln(‘1 0 1‘);
writeln(‘0 0 1‘);
writeln(‘2 0 1‘);
writeln(‘1 0 1‘);
outit;
end
else begin
writeln(-1);
outit;
end;
end
else if (map[1,1]=1)and(map[1,2]=0)and(map[1,3]=1)and(map[1,4]=0)and(map[1,5]=1) then
begin//1 0 1 0 1
if n=2 then
begin
writeln(‘0 0 1‘);
writeln(‘4 0 -1‘);
outit;
end
else if n=3 then
begin
writeln(‘0 0 1‘);
writeln(‘2 0 1‘);
writeln(‘1 0 1‘);
outit;
end
else begin
writeln(-1);
outit;
end;
end
else begin
writeln(-1);
outit;
end;
end;
procedure main;
var
i:longint;
flag:boolean;
begin
flag:=true;
for i:=1 to 5 do
if map[2,i]<>0 then
flag:=false;//flag=true时表示第二行没有方块 即只有第一行有方块
if flag then percent30;//处理30%的数据 都在最下面一行 即map[1,1~5]
if not flag then writeln(-1);//剩下的直接cheat -1
end;
begin
//init;
readdata;
main;
//outit;
end.
满分做法:
program
type
state=array[1..10,1..10] of longint;
arr=array[1..10] of longint;
var
map:state;len:arr;
p:array[1..10] of record x,y,z:longint;end;
n,i,j,tmp,t,tt,pt : longint;
procedure doit(x,y,g:longint;var map:state; var len:arr);
var
tmp,i,j,k,color,t:longint; flag:boolean;
begin
if g=-1 then
begin tmp:=map[x,y];map[x,y]:=map[x-1,y];map[x-1,y]:=tmp;end
else
if g=1 then
begin tmp:=map[x,y];map[x,y]:=map[x+1,y];map[x+1,y]:=tmp;end;
if map[x,y]=0 then
begin
for j:=y downto 1 do
if map[x+g,j]=0 then break;
map[x+g,j]:=map[x+g,y]; map[x+g,y]:=0;len[x+g]:=j;
end;
repeat
flag:=false;
for i:=1 to 5 do
for j:=1 to 7 do
begin
if map[i,j]=0 then continue;
color:=map[i,j];
if i<=3 then
begin
t:=1;
for k:=1 to 2 do
if map[i+k,j]=color then inc(t);
if t=3 then
begin for k:=0 to 2 do map[i+k,j]:=0;flag:=true;end;
end;
if j>=3 then
begin
t:=1;
for k:=1 to 2 do if map[i,j-k]=color then inc(t);
if t=3 then
begin for k:=0 to 2 do map[i,j-k]:=0;flag:=true;end;
end;
end;
if flag then
begin
for i:=1 to 5 do
begin
for j:=1 to 7 do if map[i,j]=0 then break;
for k:=j+1 to 7 do if map[i,k]<>0 then break;
if map[i,k]=0 then continue
else
begin
move(map[i,k],map[i,j],4*(len[i]-k+1));
for j:=j+len[i]-k+1 to 7 do map[i,j]:=0;
end;
end;
for i:=1 to 5 do
begin
for j:=1 to 7 do if map[i,j]=0 then break;
len[i]:=j-1;
end;
end;
until not flag;
end;
procedure dfs(max,depth:integer;map:state;len:arr);
var bak:state; bak2:arr;i,j,zz,way:longint;
begin
zz:=0;
for i:=1 to 5 do inc(zz,len[i]);
if zz=0 then
begin
for i:=1 to pt do writeln(p[i].x-1,‘ ‘,p[i].y-1,‘ ‘,p[i].z); close(input);close(output);halt;
end;
if depth>max then exit;
way:=0; inc(tt); bak:=map; bak2:=len;
if tt>40000000 then begin writeln(‘-1‘);close(input);close(output);halt;end;
for i:=1 to 5 do
for j:=1 to len[i] do
begin
if i<5 then
begin
doit(i,j,1,map,len);inc(pt);
p[pt].x:=i; p[pt].y:=j; p[pt].z:=1;
dfs(max,depth+1,map,len);
dec(pt); map:=bak; len:=bak2;
end;
if i>1 then
begin
doit(i,j,-1,map,len);inc(pt); p[pt].x:=i;p[pt].y:=j;p[pt].z:=-1;
dfs(max,depth+1,map,len); dec(pt); map:=bak; len:=bak2;
end;
end;
end;
begin
assign(input,‘mayan.in‘);reset(input); assign(output,‘mayan.out‘);rewrite(output);
readln(n);
for i:=1 to 5 do
begin
t:=0;
while not eoln do
begin
read(tmp);
if tmp<>0 then begin inc(t);map[i,t]:=tmp;end;
len[i]:=t;
end;
readln;
end;
dfs(n,1,map,len);
writeln(‘-1‘);
close(input); close(output);
end.
program mayan;
typetyy=array[0..10,0..10] of longint;
varf:tyy;
n,i,a,b:longint;
x,y,z:array[0..10] of longint;
function jiancha(ff:tyy):boolean; //检查最低层是否都消去
vari,j:longint;
begin
for i:=0 to 4 do
if ff[i,0]<>0 then exit(false);
exit(true)
end;
procedure print;
vari:longint;
begin
for i:=1 to n do
writeln(x[i],‘ ‘,y[i],‘ ‘,z[i]);
{close(input); close(output);}
halt; //若有多种方案则以x为第一关键字按字典序输出,因为搜索时按x从0到4搜索的,故找到第一种方案是可以直接退出程序
end;
procedure dfs(k:longint; ff:tyy);
forward;
procedure check(k:longint; ff:tyy);
varbt:array[0..4,0..7] of boolean;
boo:boolean;
i,j,kk,t:longint;
begin
boo:=false;
while (not boo) do //判断是否能下降,若没有下降则说明没有能消除的方块
begin
for i:=0 to 4 do for j:=0 to 7 do bt[i,j]:=false; //初始化bt,记录能否消除
for i:=0 to 4 do for j:=0 to 7 do //消除三个连续相同的
begin
if ff[i,j]=0 then continue;
if (ff[i,j]=ff[i,j+1])and(ff[i,j+1]=ff[i,j+2])and(ff[i,j]<>0)then
begin
bt[i,j]:=true;
bt[i,j+1]:=true;
bt[i,j+2]:=true;
end;
if (ff[i,j]=ff[i+1,j])and(ff[i+1,j]=ff[i+2,j])and(ff[i,j]<>0)then
begin
bt[i,j]:=true;
bt[i+1,j]:=true;
bt[i+2,j]:=true;
end;
end;
for i:=0 to 4 do for j:=0 to 7 do if bt[i,j] then ff[i,j]:=0;
boo:=true;
for i:=0 to 4 do //下降
for j:=0 to 7 do
if ff[i,j]=0 then
begin
t:=j;
while (t<=7)and(ff[i,t]=0) do inc(t);
if t>7 then break;
for kk:=0 to t-j do
begin
ff[i,j+kk]:=ff[i,t+kk];
ff[i,t+kk]:=0;
end;
boo:=false;
end;
if boo then break;
end;
if (k<>n+1)and(jiancha(ff)) then exit; //若不是在规定步数走完,则退出
if (k=n+1)and(jiancha(ff)) then print; //若恰好在规定步数消完,则输出
dfs(k,ff);
end;
procedure dfs(k:longint; ff:tyy);
vari,j,tt:longint;
begin
ifk>n then exit;
for j:=0 to 4 do
for i:=0 to 7 do
begin
if (ff[j,i]=0)then break;
if (ff[j-1,i]=0)and(j<>0)and(ff[j,i]<>ff[j-1,i]) then //若可以交换,则尝试交换
begin
x[k]:=j; y[k]:=i; z[k]:=-1;
tt:=ff[j,i]; ff[j,i]:=ff[j-1,i]; ff[j-1,i]:=tt;
check(k+1,ff);
tt:=ff[j,i]; ff[j,i]:=ff[j-1,i]; ff[j-1,i]:=tt;
x[k]:=0; y[k]:=0; z[k]:=0;
end;
if j=4 then continue; //若搜索到最后一列,则不能向右移动,退出本次循环
if ff[j,i]=ff[j+1,i] then continue;
x[k]:=j; y[k]:=i; z[k]:=1;
tt:=ff[j,i]; ff[j,i]:=ff[j+1,i]; ff[j+1,i]:=tt;
check(k+1,ff);
tt:=ff[j,i]; ff[j,i]:=ff[j+1,i]; ff[j+1,i]:=tt;
x[k]:=0; y[k]:=0; z[k]:=0;
end;
end;
begin
{assign(input,‘mayan.in‘);reset(input);
assign(output,‘mayan.out‘);rewrite(output);}
readln(n);
for i:=0 to 4 do //读入数据
begin
b:=-1;
repeat
read(a);
inc(b);
f[i,b]:=a;
until a=0;
end;
x[0]:=-1; y[0]:=-1; z[0]:=-2; //将x、y、z数组初始化
dfs(1,f);
writeln(‘-1‘); //若没有解决方案,输出-1
{close(input);
close(output);}
end.
版权声明:本文为博主原创文章,未经博主允许不得转载。