1. 程式人生 > >luogu P1312 Mayan遊戲

luogu P1312 Mayan遊戲

題面

題目描述
$ Mayan puzzle $是最近流行起來的一個遊戲。遊戲介面是一個 \(7行 \times 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 所示的局面。

輸入輸出格式
輸入格式:
共 6 行。

第一行為一個正整數\(n\),表示要求遊戲通關的步數。

接下來的\(5\)行,描述$ 7 \times 5$的遊戲介面。每行若干個整數,每兩個整數之間用一個空格隔開,每行以一個$0 $結束,自下向上表示每豎列方塊的顏色編號(顏色不多於\(10\)

種,從\(1\)開始順序編號,相同數字表示相同顏色)。

輸入資料保證初始棋盤中沒有可以消除的方塊。

輸出格式:
如果有解決方案,輸出\(n\)行,每行包含\(3\)個整數\(x,y,g\),表示一次移動,每兩個整數之間用一個空格隔開,其中\((x,y)\)表示要移動的方塊的座標,\(g\)表示移動的方向,\(1\)表示向右移動,\(−1\)表示向左移動。注意:多組解時,按照xx為第一關健字,\(y\)為第二關健字,\(1\)優先於\(−1\),給出一組字典序最小的解。遊戲介面左下角的座標為\((0,0)\)

如果沒有解決方案,輸出一行,包含一個整數\(-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

說明
【輸入輸出樣例說明】
按箭頭方向的順序分別為圖\(6\)到圖\(11\)
樣例輸入的遊戲局面如上面第一個圖片所示,依次移動的三步是:\((2,1)\)處的方格向右移動,\((3,1)\)處的方格向右移動,\((3,0)\)處的方格向右移動,最後可以將棋盤上所有方塊消除。

【資料範圍】
對於\(30%\)的資料,初始棋盤上的方塊都在棋盤的最下面一行;
對於\(100%\)的資料,\(0<n≤5\)

思路

覺得這道題寫得挺有意思的,思路有空再補吧233,程式碼也沒註釋……

程式碼

#include<iostream>
#include<cstdio>
#include<cstdlib>
#define re register
using namespace std;
//全域性變數
int n;//步數
int step[10][10][10];//dfs狀態回溯 
struct result_ans {
    int x,y,way;
}ans[10];//答案儲存 
// Mayan遊戲實現部分 
struct Mayan_puzzle {
    int a[10][10];//color <=10
    int ax[105],ay[105],T;
    inline bool go() {    //遊戲進行-判斷是否可以消除並消除 
        T=0;    int flag=0;
        for(re int i=0;i<=2;i++)
            for(re int j=0;j<=6;j++) if(a[i][j]) {
            if(a[i][j]==a[i+1][j]&&a[i+1][j]==a[i+2][j]) {
                flag = 1; ax[++T] = i; ay[T] = j;
                ax[++T]=i+1; ay[T]=j; ax[++T]=i+2; ay[T]=j;
            }
        }
        for(re int i=0;i<=4;i++)
            for(re int j=0;j<=4;j++) if(a[i][j]) {
            if(a[i][j]==a[i][j+1]&&a[i][j+1]==a[i][j+2]) {
                flag = 1; ax[++T] = i; ay[T] = j;
                ax[++T]=i; ay[T]=j+1; ax[++T]=i; ay[T]=j+2;
            }
        }   
        for(re int i=1;i<=T;i++) a[ax[i]][ay[i]]=0;
        return flag;
    }
    inline void down() {    //下降處理-懸空方塊下落 
        for(re int i=0;i<=4;i++)
            for(re int j=1;j<=6;j++) if(a[i][j])    {
            int k=j;
            while(a[i][k-1]==0) {
                swap(a[i][k-1],a[i][k]);
                if(k==1) break; else k--;
            }
        }
    }
    inline bool check() {   //結束判斷-判斷是否全部消除 
        for(re int i=0;i<=4;i++)
            if(a[i][0]) return false;
        return true;
    }
};
struct Mayan_puzzle p;
// in / out 輸入輸出 
inline void getin() {
    int color=0,T;  scanf("%d",&n);
    for(re int i=0;i<=4;i++) {  T=-1;
        while(scanf("%d",&color)&&color) p.a[i][++T]=color;
    }
}
inline void print() {
    for(re int i=1;i<=n;i++)
        printf("%d %d %d\n",ans[i].x,ans[i].y,ans[i].way);
}
// dfs 搜尋部分 
void dfs(int cur) {
    if(cur>n) {
        if(p.check()) {
            print();//out
            exit(0);//退出程式 
        }
        return;
    }
    for(re int i=0;i<=4;i++)
        for(re int j=0;j<=6;j++)
    {   
        if(p.a[i][j]&&i<=3) {   //right
            for(re int k=0;k<=4;k++)
                for(re int l=0;l<=6;l++)
                    step[cur][k][l] = p.a[k][l];
            swap( p.a[i][j] , p.a[i+1][j] );
            ans[cur].x =i; ans[cur].y =j; ans[cur].way =1;
            p.down();
            while( p.go())  p.down();
            dfs(cur+1);
            for(re int k=0;k<=4;k++)
                for(re int l=0;l<=6;l++)
                    p.a[k][l] = step[cur][k][l];
        }
        if(p.a[i][j]&&p.a[i-1][j]==0&&i>=1) {   //left
            for(re int k=0;k<=4;k++)
                for(re int l=0;l<=6;l++)
                    step[cur][k][l] = p.a[k][l];
            swap( p.a[i][j] , p.a[i-1][j] );
            ans[cur].x =i; ans[cur].y =j; ans[cur].way =-1;
            p.down();
            while( p.go())  p.down();
            dfs(cur+1);
            for(re int k=0;k<=4;k++)
                for(re int l=0;l<=6;l++)
                    p.a[k][l] = step[cur][k][l];
        }
    }
}
//main函式 
int main() {
    getin();//in
    dfs(1);//dfs
    printf("-1\n");//無解時輸出-1 
    return 0;
}