1. 程式人生 > 其它 >2022.3.17

2022.3.17

藍書

AcWing 185. 瑪雅游戲

思路:由於n<=5,可以暴力搜尋,但是要模擬很多過程非常麻煩,當三個或以上的相同顏色的塊連在一起的時候得把他們同時刪去。同時還得判斷是否能夠構成方案,如果最後有任意一個顏色的塊的數量為<=2說明肯定不能連成三個以上的了,這時就說明無解。首先讀入的時候將所有有顏色的塊的和以及它們分別和都求出來。在dfs的時候判斷當前是想左還是向右,然後進行交換。在更新狀態的時候需要吧懸空的塊都讓他落下來,並且還要檢視哪些塊是連在一起的然後將他們刪除,此時還需要更新總和和各自的和。記得還要備份和還原現場。
寫了一上午還是沒有寫出來,最後看了題解。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=10+10,INF=1e8;
int n,mp[N][N], bmp[N][N][N];
int cnt[N], bcnt[N][N],vis[N][N];
struct node
{
    int x, y, op;
} ans[N];
bool check()
{
    for (int i = 1; i <= 10; i++)
        if (cnt[i] == 1 || cnt[i] == 2)
            return 0;
    return 1;
}
void drop()
{
    for (int i = 0; i < 5; i++)
    {
        int k = 0;
        for (int j = 0; j < 7; j++)
            if (mp[i][j])
                mp[i][k++] = mp[i][j];
        while (k < 7) mp[i][k++] = 0;
    }
}
bool remove()
{
    int f=0;
    memset(vis, 0, sizeof vis);
    for (int x = 0; x < 5; x ++ )
    {
        for (int y = 0; y < 7; y ++ )
            if (mp[x][y])
            {
                int l = x, r = x;
                while (l - 1 >= 0 && mp[l - 1][y] == mp[x][y]) l--;
                while (r + 1 < 5 && mp[r + 1][y] == mp[x][y]) r++;

                if (r - l + 1 >= 3)
                {
                    f = 1;
                        vis[x][y] = 1;
                }
                else
                {
                    l = r = y;
                    while (l - 1 >= 0 && mp[x][l - 1] == mp[x][y]) l--;
                    while (r + 1 < 7 && mp[x][r + 1] == mp[x][y]) r++;

                    if (r - l + 1 >= 3)
                    {
                        f = 1;
                        vis[x][y] = 1;
                    }
                }
            }
    }

    if (f)
    {
        for (int x = 0; x < 5; x ++ )
        for (int y = 0; y < 7; y ++ )
            if (vis[x][y])
            {
                    cnt[0] --;
                    cnt[mp[x][y]] --;
                    mp[x][y] = 0;
            }
    }
    return f;
}
void update()
{
    while(1)
    {
        drop();
        if(!remove())
            break;
    }
}
bool dfs(int dep)
{
    if (dep == n) return !cnt[0];
    if(!check())
        return 0;

    memcpy(bmp[dep], mp, sizeof mp);
    memcpy(bcnt[dep], cnt, sizeof cnt);
    for (int x = 0; x < 5; x ++ )
        for (int y = 0; y < 7; y ++ )
            if (mp[x][y])
            {
                int xx = x + 1;
                if (xx < 5)
                {
                    ans[dep] = { x, y, 1 };
                    swap(mp[x][y], mp[xx][y]);
                    update();
                    if (dfs(dep + 1)) return 1;
                    memcpy(mp, bmp[dep], sizeof mp);
                    memcpy(cnt, bcnt[dep], sizeof cnt);
                }
                xx = x - 1;
                if (xx >= 0 && mp[xx][y]==0)
                {
                    ans[dep] = { x, y, -1 };
                    swap(mp[x][y], mp[xx][y]);
                    update();
                    if (dfs(dep + 1)) return 1;
                    memcpy(mp, bmp[dep], sizeof mp);
                    memcpy(cnt, bcnt[dep], sizeof cnt);
                }
            }

    return 0;

}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin>>n;
    for (int i = 0; i < 5;i++)
    {
        int x,j=0;
        while(cin>>x&&x)
        {
            cnt[0]++;
            cnt[x]++;
            mp[i][j++] = x;
        }
    }
     if (dfs(0))
    {
        for (int i = 0; i < n; i++)
        cout<<ans[i].x<<' '<<ans[i].y<<' '<< ans[i].op<<'\n';
    }
    else
        cout << -1 << '\n';
    return 0;
}