洛谷P1312 Mayan游戏——dfs

题目:https://www.luogu.org/problemnew/show/P1312

思路:

如果当前点与其右边点同色(或都不存在),则剪枝进行优化。

如果当前点有方块,则向左移,如果当前点没有方块,则其右边方块往左移。

所以只需要关注第0-4列的点,共计28个状态。

交换两个点后,再让方块掉落,掉落后再消除方块,如果又可以有方块掉落,则再掉落,然后可以消除,则再消除,直到不能消除为止——从而交换两个点后,应该采用循环来处理掉落与消除。

回溯,应该回溯到交换两个点之前的状态。可以用memcpy函数,节省代码量。

说到底,本题不难,关键在于处理好全局变量、局部变量,码之时要仔细,不要把i写成j,或者弄错横、纵坐标,更关键的是,码之前手工模拟清楚。

本题还可以再优化,比如某种颜色最后剩下块数少于3块,肯定消除不完,

AC代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
using namespace std;
int n,map[6][8],vis[6][8];
int x[6],y[6],g[6];
 
void tmpprint(){
    for(int j=6;j>=0;j--){
        for(int i=0;i<=4;i++)
            if(map[i][j])cout<<map[i][j];
            else cout<<' ';
        cout<<"\n";
    }
         
}
void diaoluo(){
    for(int i=0;i<=4;i++){
        for(int j=0;j<=5;j++){
            if(map[i][j])continue;
            for(int k=j+1;k<=6;k++){
                if(map[i][k]==0)continue;
                map[i][j]=map[i][k];
                map[i][k]=0;
                break;//important!!!
            }
        }       
    }       
}
bool xiaochu(){
    bool flg=0;
    for(int i=0;i<=4;i++)
        for(int j=0;j<=4;j++)
            if(map[i][j]==map[i][j+1]
            && map[i][j]==map[i][j+2]
            && map[i][j]){
                vis[i][j]=vis[i][j+1]=vis[i][j+2]=1;
                flg=1;
            }   
    for(int j=0;j<=6;j++)
        for(int i=0;i<=2;i++)
            if(map[i][j]==map[i+1][j]
            && map[i][j]==map[i+2][j]
            && map[i][j]){
                vis[i][j]=vis[i+1][j]=vis[i+2][j]=1;
                flg=1;
            }           
    for(int i=0;i<=4;i++)
        for(int j=0;j<=6;j++)
            if(vis[i][j]==1){
                map[i][j]=0;
                vis[i][j]=0;
            }
    if(flg){
        return 1;
    }
    else return 0;
}
bool judge(){
    for(int i=0;i<=4;i++)
        for(int j=0;j<=6;j++)
            if(map[i][j])return 0;
    return 1;
}
void dfs(int stp){  
    if(stp>n){
        if(judge()){
                for(int i=1;i<=n;i++)
                    printf("%d %d %d\n",x[i],y[i],g[i]);
                exit(0);
        }
        return;
    }
 
    for(int i=0;i<=3;i++)
        for(int j=0;j<=6;j++)
            if(map[i][j]!=map[i+1][j]){//剪枝优化
                    //写成map[i][j]==map[i][j+1]检查用时1个小时!!! 
                if(map[i][j]==0)x[stp]=i+1,y[stp]=j,g[stp]=-1;//记录 
                else x[stp]=i,y[stp]=j,g[stp]=1;
                 
                int tmpmap[6][8];//局部变量。important!!! 
                memcpy(tmpmap,map,sizeof(tmpmap)); 
                 
                swap(map[i][j],map[i+1][j]);
                diaoluo();
                while(xiaochu())diaoluo();
                    //写成while(xiaochu())diaoluo;
                    //检查用时1个小时!!! 
                 
                dfs(stp+1);
                 
                memcpy(map,tmpmap,sizeof(map));//回溯
            }
}
int main(){
//  freopen("in.txt","r",stdin);
    cin>>n;
    for(int i=0;i<=4;i++){
        int x,j=0;
        while(scanf("%d",&x)&&x) map[i][j++]=x;
    }//i列,j行
     
    dfs(1);
     
    printf("-1\n");
    return 0;   
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值