1 条题解

  • 1
    @ 2026-3-11 20:01:20
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    
    int n;
    int g[5][7], bg[5][5][7];
    int cnt[11], bcnt[5][11];
    bool st[5][7];
    
    struct Path{
        int x, y, d;
    }path[5];
    
    void move(int a, int b, int c){
        swap(g[a][b], g[c][b]);
    
        while (true){//一直循环,直到flag = true表示没找到可以继续消除的方格。
            bool flag = true;
            //处理悬空方格
            for (int x = 0; x < 5; x ++ ){
                int z = 0;
                for (int y = 0; y < 7; y ++ )
                    if (g[x][y])//如果有数字就从z开始填,并且z++, 如果没数字则跳过。
                        g[x][z ++] = g[x][y];
                while (z < 7) g[x][z ++] = 0;
            }
    
            memset(st, 0, sizeof st);
    
            for (int x = 0; x < 5; x ++ )
                for (int y = 0; y < 7; y ++ )
                    if (g[x][y]){
                        int l = x, r = x;
                        while (l - 1 >= 0 && g[l - 1][y] == g[x][y]) l --;
                        while (r + 1 < 5 && g[r + 1][y] == g[x][y]) r ++;
                        if (r - l + 1 >= 3){
                            st[x][y] = true;
                            flag = false;
                        }
                        else {
                            l = r = y;
                            while (l - 1 >= 0 && g[x][l - 1] == g[x][y]) l --;
                            while (r + 1 < 7 && g[x][r + 1] == g[x][y]) r ++;
    
                            if (r - l + 1 >= 3){
                                st[x][y] = true;
                                flag = false;
                            }
                        }
                    }
    
            if (flag) break;
    
            for (int x = 0; x < 5; x ++ )
                for (int y = 0; y < 7; y ++ )
                    if (st[x][y]){
                        cnt[0] --;
                        cnt[g[x][y]] --;
                        g[x][y] = 0;
                    }
        }
    }
    
    bool dfs(int u){
        if (u == n) return !cnt[0];
    
        for (int i = 1; i <= 10; i ++ )
            if (cnt[i] == 1 || cnt[i] == 2)
                return false;
    
        memcpy(bg[u], g, sizeof g); //备份现场
        memcpy(bcnt[u], cnt, sizeof cnt);
    
        for (int x = 0; x < 5; x ++ )
            for (int y = 0; y < 7; y ++ )
                if (g[x][y]){
                    int nx = x + 1;
                    if (nx < 5){
                        path[u] = {x, y, 1};
                        move(x, y, nx);
                        if (dfs(u + 1)) return true;
                        memcpy(g, bg[u], sizeof g);//因为move函数后会改变原来的图形g
                        memcpy(cnt, bcnt[u], sizeof cnt);//move后会改变原来图形数字的数量cnt
                    }
    
                    nx = x - 1;
                    if (nx >= 0 && !g[nx][y]){//这里如果能够左移的话,必须保证左边为空,具体见剪枝2.
                        path[u] = {x, y, -1};
                        move(x, y, nx);
                        if (dfs(u + 1)) return true;
                        memcpy(g, bg[u], sizeof g);
                        memcpy(cnt, bcnt[u], sizeof cnt);
                    }
                }
        return false;
    }
    
    
    int main(){
        scanf("%d", &n);
    
        for (int x = 0; x < 5; x ++ ){
            int t, y = 0;
            while (scanf("%d", &t), t){
                cnt[0] ++;//记录总共有多少个数
                cnt[t] ++;//记录数字t的有多少个,方便dfs里剪枝
                g[x][y ++] = t;
            }
        }
    
        if (dfs(0)){
            for (int i = 0; i < n; i ++ ) printf("%d %d %d\n", path[i].x, path[i].y, path[i].d);
        }else puts("-1");
    
        return 0;
    }
    
    • 1

    信息

    ID
    96
    时间
    3000ms
    内存
    128MiB
    难度
    4
    标签
    递交数
    28
    已通过
    16
    上传者