P1312 [NOIP2011 提高组] Mayan 游戏

//URL: https://www.luogu.com.cn/problem/P1312
/*
7*5的 棋盘  问最少几次可以清空 
1.将(i,j) 左/右 交换 val-> null/val
2.行或列 有连续3个方块 会自动消掉  
 *    *
 *      *            包括这样的连通块 
***   ***
3.每次操作后 会自动下落

通关次数 <=5 自然是深搜 
1.check  all clear
2.move change r/l
3.remove clear 连通块
4.update auto fall
5.dfs 每次记录操作 深搜
6.copy 用以回溯 直接交换有WA 因为会继续反应 
 
剪枝: 因为优先级 1 》-1  所以尽量 1 
所以从左向右 若右边有方块且不同(可以==0) 就交换 若左边有方块早就1 交换了
若左边 null 可以交换
*/
/*
3
1 0
2 1 0
2 3 4 0
3 1 0
2 4 3 4 0

2 1 1
3 1 1
3 0 1
*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<string.h>
//#include<queue>
//#include<vector>
#include<bits/stdc++.h>
#define ll long long
#define ddd printf("-----------------------\n");
using namespace std;
const int maxn=1e1 +10;
const int mod=998244353;
const int inf=0x3f3f3f3f;

int n,mp[10][10],xiao[10][10],last[10][10][10],ans[10][10];

int check()
{
    for(int i=1;i<=5;i++)
        if(mp[i][1]) return 0;//mp[i][1]<-mp[1][i]
    return 1;
}
int remove()
{
    //memset(xiao,0,sizeof(xiao));
    int flag=0;
    for(int i=1;i<=5;i++)
    {
        for(int j=1;j<=7;j++)
        {
            if(mp[i][j]&&i-1>=1&&i+1<=5&&mp[i][j]==mp[i-1][j]&&mp[i][j]==mp[i+1][j]){
                xiao[i-1][j]=1;xiao[i+1][j]=1;xiao[i][j]=1;flag=1;
            }
            if(mp[i][j]&&j-1>=1&&j+1<=7&&mp[i][j]==mp[i][j+1]&&mp[i][j]==mp[i][j-1]){
                xiao[i][j]=1;xiao[i][j+1]=1;xiao[i][j-1]=1;flag=1;
            }
        }
    }
    if(flag==0) return 0;
    for(int i=1;i<=5;i++)
        for(int j=1;j<=7;j++)
            if(xiao[i][j]==1) xiao[i][j]=0,mp[i][j]=0;
    return 1;    
}
void update()
{
    for(int i=1;i<=5;i++){
        int cnt=0;
        for(int j=1;j<=7;j++)
        {
            if(mp[i][j]==0) cnt++;
            else{
                if(cnt==0) continue;//!!!!!!!!!!!!!!!!!!!!!!!!
                mp[i][j-cnt]=mp[i][j];
                mp[i][j]=0;
            }            
        }
    }
}
void move(int i,int j,int x)
{
    
    int tmp=mp[i+x][j];
    mp[i+x][j]=mp[i][j];
    mp[i][j]=tmp;
    update();
    while(remove()) update();
}
void copy(int x)
{
    for(int i=1;i<=5;i++)
        for(int j=1;j<=7;j++)
            last[x][i][j]=mp[i][j];
}
void dfs(int x)
{
    if(check()){
        for(int i=1;i<=n;i++)
            cout<<ans[i][1]<<" "<<ans[i][2]<<" "<<ans[i][3]<<'\n';
        exit(0);
    } 
    if(x>=n+1) return;//!!!!!!!!!!!!!!!!
    copy(x);
    for(int i=1;i<=5;i++){
        for(int j=1;j<=7;j++)//if mp[][]!=0 move 
        {
            if(mp[i][j])//
            {
                if(i+1<=5&&mp[i][j]!=mp[i+1][j])//右边任然可以是null
                {
                    move(i,j,1); ans[x][1]=i-1,ans[x][2]=j-1,ans[x][3]=1;
                    dfs(x+1);
                    for(int xx=1;xx<=5;xx++)
                        for(int yy=1;yy<=7;yy++)
                            mp[xx][yy]=last[x][xx][yy];
                    ans[x][1]=-1,ans[x][2]=-1,ans[x][3]=-1;
                }
                if(i-1>=1&&mp[i-1][j]==0)////!!!!!!!!!!!!!!!!
                {
                    move(i,j,-1); ans[x][1]=i-1,ans[x][2]=j-1,ans[x][3]=-1;
                    dfs(x+1);
                    for(int xx=1;xx<=5;xx++)
                        for(int yy=1;yy<=7;yy++)
                            mp[xx][yy]=last[x][xx][yy];
                    ans[x][1]=-1,ans[x][2]=-1,ans[x][3]=-1;
                }    
            }
        }
    }
}

int main()
{
    ios::sync_with_stdio(false);
    
    memset(ans,-1,sizeof(ans));
    cin>>n;
    for(int i=1;i<=5;i++){
        for(int j=1;j<=8;j++){
            int tmp;cin>>tmp;
            if(tmp==0) break;
            mp[i][j]=tmp;
        }
    }
    dfs(1);
    cout<<"-1\n";
    
    return 0;
}

 

posted @ 2023-10-28 11:18  JMXZ  阅读(80)  评论(0)    收藏  举报