題目
題目描述
Mayan puzzle
是最近流行起來的一個遊戲。遊戲界面是一個77 行\times 5×5列的棋盤,上面堆放着一些方塊,方塊不能懸空堆放,即方塊必須放在最下面一行,或者放在其他方塊之上。遊戲通關是指在規定的步數內消除所有的方塊,消除方塊的規則如下:
1 、每步移動可以且僅可以沿橫向(即向左或向右)拖動某一方塊一格:當拖動這一方塊時,如果拖動後到達的位置(以下稱目標位置)也有方塊,那麼這兩個方塊將交換位置(參見輸入輸出樣例說明中的圖66到圖77 );如果目標位置上沒有方塊,那麼被拖動的方塊將從原來的豎列中抽出,並從目標位置上掉落(直到不懸空,參見下面圖1 和圖2);
2 、任一時刻,如果在一橫行或者豎列上有連續三個或者三個以上相同顏色的方塊,則它們將立即被消除(參見圖1 到圖3)。
注意:
a) 如果同時有多組方塊滿足消除條件,幾組方塊會同時被消除(例如下面圖44 ,三個顏色爲11 的方塊和三個顏色爲 22 的方塊會同時被消除,最後剩下一個顏色爲22的方塊)。
b) 當出現行和列都滿足消除條件且行列共享某個方塊時,行和列上滿足消除條件的所有方塊會被同時消除(例如下面圖5 所示的情形,5 個方塊會同時被消除)。
3 、方塊消除之後,消除位置之上的方塊將掉落,掉落後可能會引起新的方塊消除。注意:掉落的過程中將不會有方塊的消除。
上面圖1 到圖 3 給出了在棋盤上移動一塊方塊之後棋盤的變化。棋盤的左下角方塊的座標爲(0, 0 ),將位於(3, 3 )的方塊向左移動之後,遊戲界面從圖 1 變成圖 2 所示的狀態,此時在一豎列上有連續三塊顏色爲4 的方塊,滿足消除條件,消除連續3 塊顏色爲4 的方塊後,上方的顏色爲3 的方塊掉落,形成圖 3 所示的局面。
輸入格式
共 6 行。
第一行爲一個正整數nn,表示要求遊戲通關的步數。
接下來的55行,描述7 \times 57×5 的遊戲界面。每行若干個整數,每兩個整數之間用一個空格隔開,每行以一個00結束,自下向上表示每豎列方塊的顏色編號(顏色不多於1010種,從11開始順序編號,相同數字表示相同顏色)。
輸入數據保證初始棋盤中沒有可以消除的方塊。
輸出格式
如果有解決方案,輸出nn行,每行包含 33 個整數x,y,gx,y,g,表示一次移動,每兩個整數之間用一個空格隔開,其中(x ,y)(x,y)表示要移動的方塊的座標,gg 表示移動的方向,11 表示向右移動,-1−1表示向左移動。注意:多組解時,按照xx爲第一關健字,yy爲第二關健字,11優先於-1−1 ,給出一組字典序最小的解。遊戲界面左下角的座標爲(0 ,0)(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
說明/提示
【輸入輸出樣例說明】
按箭頭方向的順序分別爲圖66到圖1111
樣例輸入的遊戲局面如上面第一個圖片所示,依次移動的三步是:(2 ,1 )(2,1)處的方格向右移動,(3,1)(3,1)處的方格向右移動,(3,0)(3,0)處的方格向右移動,最後可以將棋盤上所有方塊消除。
【數據範圍】
對於30\%30%的數據,初始棋盤上的方塊都在棋盤的最下面一行;
對於100\%100%的數據,0 < n≤50<n≤5 。
noip2011提高組day1第3題
題解&分析
這道題就是一道模擬 + 搜索題。
枚舉每一步的答案,然後有幾個剪枝:
1.空格是不合法的,不能移動
2.同色的格子移動沒有用
3.對於向左移,因爲有一個右邊大於左邊的優先級,所以如果向左移要到的格子是有色的,那麼將目標格子向右移就會更優,且效果一樣
代碼:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <map>
#include <vector>
#include <algorithm>
using namespace std;
#define ll long long
int n , m , a[13][13];
int ansx[13] , ansy[13] , ansp[13];
struct node{
int x , y;
};
node chan[40];
int cnt;
int now[6][13][13];
bool check( int x , int y , int d ){
if( now[d][x-1][y] == now[d][x][y] && now[d][x][y] == now[d][x+1][y] )
return 1;
if( now[d][x+1][y] == now[d][x][y] && now[d][x+2][y] == now[d][x+1][y] )
return 1;
if( now[d][x-1][y] == now[d][x][y] && now[d][x][y] == now[d][x-2][y] )
return 1;
if( now[d][x][y-1] == now[d][x][y] && now[d][x][y] == now[d][x][y+1] )
return 1;
if( now[d][x][y+1] == now[d][x][y] && now[d][x][y+2] == now[d][x][y+1] )
return 1;
if( now[d][x][y-1] == now[d][x][y] && now[d][x][y] == now[d][x][y-2] )
return 1;
return 0;
}
void dfs( int x , int lx , int ly ){
if( x == n + 1 ){
for( int i = 1 ; i <= 7 ; i ++ )
for( int j = 1 ; j <= 5 ; j ++ ){
if( now[x-1][i][j] > 0 )
return ;
}
for( int i = 1 ; i <= n ; i ++ ){
printf( "%d %d %d\n" , ansy[i] - 1 , ansx[i] - 1 , ansp[i] );
}
exit( 0 );
}
for( int j = 1 ; j <= 5 ; j ++ ){
for( int i = 1 ; i <= 7 ; i ++ ){
/*if( x == 1 && ( i != 5 || j != 1 ) ) continue;
if( x == 2 && ( i != 3 || j != 1 ) ) continue;
if( x == 3 && ( i != 4 || j != 2 ) ) continue;
if( x == 4 && ( i != 3 || j != 4 ) ) continue;
if( x == 5 && ( i != 1 || j != 4 ) ) continue;*/
if( now[x-1][i][j] == 0 ) continue;
memcpy( now[x] , now[x-1] , sizeof( now[x] ) );
if( now[x][i][j] != now[x][i][j+1] && j != 5 ){
ansx[x] = i , ansy[x] = j , ansp[x] = 1;
if( now[x][i][j+1] == 0 ){
int k;
for( k = i - 1 ; k >= 1 ; k -- ){
if( now[x][k][j+1] ){
now[x][k+1][j+1] = now[x][i][j];
break;
}
else
now[x][k+1][j+1] = 0;
}
if( k <= 0 ){
now[x][1][j+1] = now[x][i][j];
}
for( k = i + 1 ; k <= 7 ; k ++ )
now[x][k-1][j] = now[x][k][j];
now[x][k-1][j] = 0;
}
else
swap( now[x][i][j] , now[x][i][j+1] );
while( 1 ){
memset( chan , 0 , sizeof( chan ) ); cnt = 0;
for( int ii = 7 ; ii >= 1 ; ii -- ){
for( int jj = 1 ; jj <= 5 ; jj ++ ){
if( now[x][ii][jj] == 0 ) continue;
if( check( ii , jj , x ) ){
chan[++cnt].x = ii , chan[cnt].y = jj;
}
}
}
if(!cnt) break;
for( int ii = 1 ; ii <= cnt ; ii ++ ){
int xx = chan[ii].x , y = chan[ii].y;
int k;
for( k = xx + 1 ; k <= 7 ; k ++ )
now[x][k-1][y] = now[x][k][y];
now[x][7][y] = 0;
}
}
/*printf( "x = %d %d %d %d\n" , x , i , j , ansp[x] );
for( int i = 7 ; i >= 1 ; i -- ){
for( int j = 1 ; j <= 5 ; j ++ )
printf( "%d " , now[x][i][j] );
printf( "\n" );
}*/
dfs( x + 1 , i , j );
}
memcpy( now[x] , now[x-1] , sizeof( now[x] ) );
if( now[x][i][j] != now[x][i][j-1] && j != 1 && now[x][i][j-1] == 0 ){
ansx[x] = i , ansy[x] = j , ansp[x] = -1;
if( now[x][i][j-1] == 0 ){
int k;
for( k = i - 1 ; k >= 1 ; k -- ){
if( now[x][k][j-1] ){
now[x][k+1][j-1] = now[x][i][j];
break;
}
else
now[x][k+1][j-1] = 0;
}
if( k <= 0 ){
now[x][1][j-1] = now[x][i][j];
}
for( k = i + 1 ; k <= 7 ; k ++ )
now[x][k-1][j] = now[x][k][j];
now[x][k-1][j] = 0;
}
else
swap( now[x][i][j] , now[x][i][j-1] );
while( 1 ){
memset( chan , 0 , sizeof( chan ) ); cnt = 0;
for( int ii = 7 ; ii >= 1 ; ii -- ){
for( int jj = 1 ; jj <= 5 ; jj ++ ){
if( now[x][ii][jj] == 0 ) continue;
if( check( ii , jj , x ) ){
chan[++cnt].x = ii , chan[cnt].y = jj;
}
}
}
if(!cnt) break;
for( int ii = 1 ; ii <= cnt ; ii ++ ){
int xx = chan[ii].x , y = chan[ii].y;
int k;
for( k = xx + 1 ; k <= 7 ; k ++ )
now[x][k-1][y] = now[x][k][y];
now[x][7][y] = 0;
}
}
dfs( x + 1 , i , j );
}
}
}
}
int main(){
scanf( "%d" , &n );
for( int i = 1 ; i <= 5 ; i ++ ){
int x , p = 1;
while( 1 ){
scanf( "%d" , &x );
if( !x ) break;
a[p++][i] = x;
}
}
memcpy( now[0] , a , sizeof( now[0] ) );
dfs( 1 , 0 , 0 );
printf( "-1" );
return 0;
}