Mayan遊戲 (codevs 1136)題解

【問題描述】

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所示的局面。

【樣例輸入】

    3
    1 0
    2 1 0
    2 3 4 0
    3 1 0
    2 4 3 4 0

【樣例輸出】

    2 1 1
    3 1 1
    3 0 1

【解題思路】

     本題爲NOIP2011day1第三題,初看題目感覺似乎挺難的,不僅是一條線上可以消掉,還有可能十字形的也可以消掉,還可能多組一起消掉,還可能會掉下來之後又可以消掉(頭都大了……)。但其實仔細分析一下,這題並不難,無論怎麼消,都得要滿足三個以上的方塊是同顏色,於是,我們在每一次消除的時候,可以設一個數組,它相鄰的兩個方塊和它的顏色相同的話,就代表要消除,標記起來,然後搜索一遍整個棋盤後,要消除的就全部標記了,消除即可。然後整個深搜的過程中有一個優化,就是只需要往右邊搜,(題目中說1優先於-1就是在提醒我們,往右邊搜與往左邊搜其實是一樣的)這樣也大大降低了編程複雜度,只需要判斷一下如果兩邊有一個方格爲空格的話,就判斷哪個是空格(不能移動空格,因此如果左邊爲空格就需要記錄-1),如果兩邊都爲空格的話就沒必要移動了(移了也是白移,浪費步數,相信沒人玩遊戲的時候會這麼傻)。還有最重要的一點,請看題目描述中的加粗字(這不是我加粗的,是題目本身加粗的),這意味着什麼?你是不是很頭疼還要算一算步數?可實際上,數據告訴我們,這不是計算機學會做過的數據就是題目描述有問題!看我的程序就知道了。不多說了,直接上程序。

【代碼實現】

  1 type arr=array[0..5,0..7] of longint;
  2 var a:arr;
  3     x,y,g:array[0..6] of longint;
  4     n,step,i,j,t:longint;
  5 procedure swap(var a:longint;var b:longint);
  6 var t:longint;
  7 begin
  8  t:=a;
  9  a:=b;
 10  b:=t;
 11 end;
 12 procedure print;
 13 var i:longint;
 14 begin
 15  for i:=1 to n do//沒錯這就是bug!!!我直接從1到n輸出了,當時還沒反應過來,仔細的同學們可以改爲step
 16   writeln(x[i],' ',y[i],' ',g[i]);
 17 end;
 18 function clean:longint;//刪除的操作,1爲刪除了東西,0爲沒刪除東西
 19 var f:arr;
 20     i,j,k:longint;
 21 begin
 22  fillchar(f,sizeof(f),0);
 23  k:=0;
 24  for i:=0 to 4 do
 25   for j:=0 to 6 do
 26    if a[i,j]<>0 then
 27     begin
 28      if (i>0)and(i<4)and(a[i,j]=a[i-1,j])and(a[i,j]=a[i+1,j]) then
 29       begin
 30        f[i,j]:=1;
 31        f[i-1,j]:=1;
 32        f[i+1,j]:=1;
 33       end;
 34      if (j>0)and(j<6)and(a[i,j]=a[i,j-1])and(a[i,j]=a[i,j+1]) then
 35       begin
 36        f[i,j]:=1;
 37        f[i,j-1]:=1;
 38        f[i,j+1]:=1;
 39       end;
 40     end;
 41  for i:=0 to 4 do
 42   for j:=0 to 6 do
 43    if f[i,j]<>0 then
 44     begin
 45      k:=1;
 46      a[i,j]:=0;
 47     end;
 48  exit(k);
 49 end;
 50 procedure fall;//下落操作
 51 var i,j,k:longint;
 52 begin
 53  for i:=0 to 4 do
 54   for j:=1 to 6 do
 55    if (a[i,j]<>0)and(a[i,j-1]=0) then
 56     begin
 57      k:=j;
 58      while(k>0)and(a[i,k-1]=0) do
 59       dec(k);
 60      a[i,k]:=a[i,j];
 61      a[i,j]:=0;
 62     end;
 63 end;
 64 function finish:boolean;
 65 var i,j:longint;
 66 begin
 67  for i:=0 to 4 do
 68   for j:=0 to 6 do
 69    if a[i,j]<>0 then
 70     exit(false);
 71  exit(true);
 72 end;
 73 procedure dfs;
 74 var i,j,k,l:longint;
 75     b:arr;
 76 begin
 77  if step<>0 then
 78   swap(a[x[step],y[step]],a[x[step]+g[step],y[step]]);//交換上一步的兩個格子
 79  repeat
 80   fall;
 81  until clean=0;//注意!先下落後刪除,這裏卡了好久,哭死了
 82  if step=n then
 83   if finish then
 84    begin
 85     print;
 86     halt;
 87    end
 88   else
 89    exit;
 90  for i:=0 to 4 do
 91   for j:=0 to 6 do
 92    begin
 93     if a[i,j]<>0 then
 94      begin
 95       inc(step);
 96       if (i<4)and(a[i,j]<>a[i+1,j]) then
 97        begin
 98         x[step]:=i;
 99         y[step]:=j;
100         g[step]:=1;
101         for k:=0 to 4 do
102          for l:=0 to 6 do
103           b[k,l]:=a[k,l];
104         dfs;
105         for k:=0 to 4 do
106          for l:=0 to 6 do
107           a[k,l]:=b[k,l];
108        end;
109       if (i>0)and(a[i-1,j]=0) then
110        begin
111         x[step]:=i;
112         y[step]:=j;
113         g[step]:=-1;
114         for k:=0 to 4 do
115          for l:=0 to 6 do
116           b[k,l]:=a[k,l];
117         dfs;
118         for k:=0 to 4 do
119          for l:=0 to 6 do
120           a[k,l]:=b[k,l];
121        end;
122       dec(step);
123      end;
124    end;
125  exit;
126 end;
127 begin
128  readln(n);
129  for i:=0 to 4 do
130   begin
131    t:=-1;
132    repeat
133     inc(t);
134     read(a[i,t]);
135    until a[i,t]=0;
136   end;
137  dfs;
138  writeln(-1);
139 end.

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章