Mayan 遊戲

題目

題目描述

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;
}

 

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