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

luogu P1312 Mayan遊戲

坐標 names set 分享 第一個 mat mem space 沒有

題目描述

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

輸入輸出格式

輸入格式:

輸入文件mayan.in,共 6 行。

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

接下來的5 行,描述 7*5 的遊戲界面。每行若幹個整數,每兩個整數之間用一個空格隔開,每行以一個0 結束,自下向上表示每豎列方塊的顏色編號(顏色不多於10種,從1 開始順序編號,相同數字表示相同顏色)。

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

輸出格式:

輸出文件名為mayan.out。

如果有解決方案,輸出 n 行,每行包含 3 個整數x,y,g ,表示一次移動,每兩個整數之間用一個空格隔開,其中(x ,y)表示要移動的方塊的坐標,g 表示移動的方向,1 表示向右移動,-1表示向左移動。註意:多組解時,按照 x 為第一關健字,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 。

noip2011提高組day1第3題

/*
定義的ans數組有x,y,移動方向
讀入
dfs(步數)
  當步數大於n時,判斷是否完全消除(),若完全消除,輸出
  統計是否有數的個數已經小於3,若有,退出
  沒有
    遍歷所有點,當此點與右邊的點不同顏色時
    加入answer
    交換
    下落(多次下落,下落消除後,繼續下落)
    while(消除()) 下落()

    dfs(步數 + 1)
    回溯
*/

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <iostream>

using namespace std;
const int N = 10;

struct Node{
    int x, y, ho;
}answer[N];
int n;
int a[N][N];

inline int read()
{
    int x = 0; char c = getchar();
    while(c < 0 || c > 9)c = getchar();
    while(c >= 0 && c <= 9)x = x * 10 + c - 0, c = getchar();
    return x;
}

void drop()
{
    int num[N][N];
    memset(num, -1, sizeof(num));
    for(int i = 0; i < 5; i ++)
    {
        int h = 0;
        for(int j = 0; j < 7; j ++)
            if(a[i][j])
                num[i][h ++] = j;
    }
    for(int i = 0; i < 5; i ++)
        for(int j = 0; j < 7; j ++)
            a[i][j] = num[i][j] == -1 ? 0 : a[i][num[i][j]];
    return ;
}

bool empty()
{
    for(int i = 0; i < 5; i ++)
        for(int j = 0; j < 7; j ++)
            if(a[i][j])
                return 0;
    return 1;
}

bool clear()
{
    bool ret_flag = 0;
    for(int i = 0; i < 3; i ++)
        for(int j = 0; j < 7; j ++)
            if(a[i][j])
            {
                int x = i;
                while(x < 4 && a[i][j] == a[x + 1][j]) x ++;
                if(x - i >= 2)
                {
                    for(int xx = i; xx <= x; xx ++)
                    {
                        int up = j;
                        int dn = j;
                        while(a[xx][up + 1] == a[i][j] && up < 6) up ++;
                        while(a[xx][dn - 1] == a[i][j] && dn > 0) dn --;
                        if(up - dn >= 2)
                            for(int y_ = dn; y_ <= up; y_ ++)
                                a[xx][y_] = 0;
                    }
                    for(int x_ = i; x_ <= x;  x_ ++)
                        a[x_][j] = 0;
                    ret_flag = 1;
                }
            }
    for(int i = 0; i < 5; i ++)
        for(int j = 0; j < 5; j ++)
            if(a[i][j])
            {
                int y = j;
                while(a[i][y + 1] == a[i][j] && y < 6) y ++;
                if(y - j >= 2)
                {
                    for(int yy = j; yy <= y; yy ++)
                    {
                        int lef = i;
                        int rig = i;
                        while(a[lef - 1][yy] == a[i][j] && lef > 0) lef --;
                        while(a[rig + 1][yy] == a[i][j] && rig < 6) rig ++;
                        if(rig - lef >= 2)
                            for(int x_ = lef; x_ <= rig; x_ ++)
                                a[x_][yy] = 0;
                    }
                    for(int y_ = j; y_ <= y; y_ ++)
                        a[i][y_] = 0;
                    ret_flag = 1;
                }
            }
    if(ret_flag) return 1;
    else return 0;
}

void dfs(int tot)
{
    if(tot > n)
    {
        if(empty())
        {
            for(int i = 1; i <= n; i ++) 
            {
                if(answer[i].ho)
                    printf("%d %d %d\n", answer[i].x + 1, answer[i].y, -1);
                else
                    printf("%d %d %d\n", answer[i].x, answer[i].y, 1);
            }
            exit(0);
        }
        return ;
    }        
    int sum[N + 1];
    memset(sum, 0, sizeof(sum));
    for(int i = 0; i < 5; i ++)
        for(int j = 0; j < 7; j ++)
            sum[a[i][j]] ++;
    for(int i = 1; i <= 10; i ++)
        if(sum[i] && sum[i] <= 2)
            return ;
    for(int i = 0; i < 4; i ++)
        for(int j = 0; j < 7; j ++)
            if(a[i][j] != a[i + 1][j])
            {
                answer[tot].x = i;
                answer[tot].y = j;
                answer[tot].ho = (!a[i][j]);
                int tmp[N][N];
                memcpy(tmp, a, sizeof(tmp));
                swap(a[i][j], a[i + 1][j]);
                drop();
                while(clear()) drop();
                dfs(tot + 1);
                answer[tot].x = 0;
                answer[tot].y = 0;
                answer[tot].ho = 0;
                memcpy(a, tmp, sizeof(a));
            }
}

int main()
{
    n = read();
    for(int i = 0; i < 5; i ++)
    {
        for(int j = 0; ; j ++)
        {
            a[i][j] = read();
            if(!a[i][j]) break;
        }    
    }
    dfs(1);
    printf("-1\n"); 
    return 0;
}
/*
3
1 0
2 1 0
2 3 4 0
3 1 0
2 4 3 4 0
*/

luogu P1312 Mayan遊戲