洛谷P1312 [NOIP 2011 提高组] Mayan 游戏

题目

#算法/进阶搜索

思路:

根据题意,我们可以知道,这题只能枚举,剪枝,因此,我们考虑如何枚举,剪枝.

首先,我们要定义下降函数down(),使得小木块右移时,能够下降到最低处,其次,我们还需要写出判断函数,判断矩阵内是否有小木块没被消除.另外,我们还需要消除函数,将矩阵内三个相连的小木块清除,dfs()函数进行搜索

这里,我们定义数组横坐标代表原矩阵的列,纵坐标代表原矩阵的行,坐标轴从1,1开始

check判断函数:

直接判断当前矩阵中是否仍存在小正方行

cpp 复制代码
  

bool check(){

    for(int i=1;i<=5;i++){

        for(int j=1;j<=7;j++){

            if(dp[i][j])return false;

        }

    }

    return true;

}

clear()清除函数

cpp 复制代码
由于我们后序每次将正方行下降后都需要判断当前是否需要清除,所以我们将clear定义为int,
判断的时候,我们三个一组的判断
1.先横向判断每一行是否有三个连续的
2.在竖向判断是否有三个连续的
注意:这里我们全部判断完后再进行删除,否则会出现4-5个连续的同色方块只能删除三个
int clear(){

    int g=0;

    int del[10][10]={0};
横向删除
    for(int i=1;i<=5;i++){

        for(int j=1;j<=7;j++){

            if(!dp[i][j])continue;

            if(i>1&&i<5){

                if(dp[i-1][j]==dp[i][j]&&dp[i][j]==dp[i+1][j]){

                    del[i-1][j]=del[i][j]=del[i+1][j]=g=1;

                }

            }

        }

     }
竖向删除
    for(int i=1;i<=5;i++){

        for(int j=2;j<=6;j++){

            if(dp[i][j]==0)continue;

            if(dp[i][j-1]==dp[i][j]&&dp[i][j]==dp[i][j+1]){

                del[i][j-1]=del[i][j]=del[i][j+1]=g=1;

            }

        }

    }

    for(int i=1;i<=5;i++){

        for(int j=1;j<=7;j++){

            if(del[i][j]==1)dp[i][j]=0;

        }

    }

    return g;

}

down()下降函数

cpp 复制代码
在下降的时候,会出现一列的小正方形多组不连续,比如1020201,我们在下降的时候需要先将第一个2下降到最底部,再将第二个2下降到最底部,最后将1下降到最底部,所以,我们从下往上降
void down(){

    for(int i=1;i<=5;i++){
从原矩阵第二行开始下降
        for(int j=2;j<=7;j++){

            if(dp[i][j]==0)continue;

            int k=j;
  这里一定要添加限定条件k-1>=1
            while(k-1>=1&&dp[i][k-1]==0){

                swap(dp[i][k],dp[i][k-1]);

                k--;

            }

        }

    }

}

dfs()函数

定义flag代表我们是否找到可删除合法方案

cpp 复制代码
void dfs(int x){
如果已经删除完了,直接返回
    if(flag)return;
    if(x>n){

        if(check()){

            for(int i=1;i<=n;i++){
res,0放原坐标轴x,1放原坐标y,2放正方向移动方向
                cout<<res[i][0]<<' '<<res[i][1]<<' '<<res[i][2]<<endl;

            }

            flag=true;

        }

        return;

    }

    for(int i=1;i<=5;i++){

        for(int j=1;j<=7;j++){

            if(dp[i][j]==0)continue;

            int tmp[10][10];
保存初始状态
            memcpy(tmp,dp,sizeof(tmp));
正方行右移
           if(i<5){

               res[x][0]=i-1;

               res[x][1]=j-1;

               res[x][2]=1;

               swap(dp[i][j],dp[i+1][j]);

              for(down();clear()!=0;down());

                dfs(x+1);
恢复初始状态
                memcpy(dp,tmp,sizeof(dp));

            }
正方向左移
            if(i>=2){

                res[x][0]=i-1;

                res[x][1]=j-1;

                res[x][2]=-1;

                swap(dp[i][j],dp[i-1][j]);

               for(down();clear()!=0;down());

                 dfs(x+1);
恢复初始状态
                 memcpy(dp,tmp,sizeof(dp));

            }

        }

    }

}

完整代码

cpp 复制代码
#include<iostream>

#include<cstring>

  

using namespace std;

int n;

int dp[10][10];

int res[30][3];

bool flag=false;

  

bool check(){

    for(int i=1;i<=5;i++){

        for(int j=1;j<=7;j++){

            if(dp[i][j])return false;

        }

    }

    return true;

}

  

int clear(){

    int g=0;

    int del[10][10]={0};

    for(int i=1;i<=5;i++){

        for(int j=1;j<=7;j++){

            if(!dp[i][j])continue;

            if(i>1&&i<5){

                if(dp[i-1][j]==dp[i][j]&&dp[i][j]==dp[i+1][j]){

                    del[i-1][j]=del[i][j]=del[i+1][j]=g=1;

                }

            }

        }

     }

    for(int i=1;i<=5;i++){

        for(int j=2;j<=6;j++){

            if(dp[i][j]==0)continue;

            if(dp[i][j-1]==dp[i][j]&&dp[i][j]==dp[i][j+1]){

                del[i][j-1]=del[i][j]=del[i][j+1]=g=1;

            }

        }

    }

    for(int i=1;i<=5;i++){

        for(int j=1;j<=7;j++){

            if(del[i][j]==1)dp[i][j]=0;

        }

    }

    return g;

}

  

void down(){

    for(int i=1;i<=5;i++){

        for(int j=2;j<=7;j++){

            if(dp[i][j]==0)continue;

            int k=j;

            while(k-1>=1&&dp[i][k-1]==0){

                swap(dp[i][k],dp[i][k-1]);

                k--;

            }

        }

    }

}

  
  
  

void dfs(int x){

    if(flag)return;

    if(x>n){

        if(check()){

            for(int i=1;i<=n;i++){

                cout<<res[i][0]<<' '<<res[i][1]<<' '<<res[i][2]<<endl;

            }

            flag=true;

        }

        return;

    }

    for(int i=1;i<=5;i++){

        for(int j=1;j<=7;j++){

            if(dp[i][j]==0)continue;

            int tmp[10][10];

            memcpy(tmp,dp,sizeof(tmp));

           if(i<5){

               res[x][0]=i-1;

               res[x][1]=j-1;

               res[x][2]=1;

               swap(dp[i][j],dp[i+1][j]);

              for(down();clear()!=0;down());

                dfs(x+1);

                memcpy(dp,tmp,sizeof(dp));

            }

            if(i>=2){

                res[x][0]=i-1;

                res[x][1]=j-1;

                res[x][2]=-1;

                swap(dp[i][j],dp[i-1][j]);

               for(down();clear()!=0;down());

                 dfs(x+1);

                 memcpy(dp,tmp,sizeof(dp));

            }

        }

    }

}

  

int main(void){

    cin>>n;

    for(int i=1;i<=5;i++){

        int cnt=1;

        int tmp;

        while(cin>>tmp&&tmp){

            dp[i][cnt]=tmp;

            cnt++;

        }

    }

    dfs(1);

    if(flag==false){

        cout<<-1<<endl;

    }

    return 0;

}
相关推荐
可编程芯片开发1 小时前
基于MPPT最大功率跟踪的离网光伏发电系统Simulink建模与仿真
算法
AI科技星1 小时前
线性算子不是空间映射函数,是全域双螺旋场之间拉伸、旋转、耦合、坍缩的跨空间标准化变换载体《全域数学vs传统数学:人类文明进阶200讲》第80讲
线性代数·算法·矩阵·数据挖掘·回归·乖乖数学·全域数学
米罗篮1 小时前
矩阵快速幂 (Exponentiation By Squaring Applied To Matrices)
c++·线性代数·算法·矩阵
dream_home84071 小时前
图像算法模型NPU适配与算法服务实战指南
人工智能·python·算法·npu 图像服务
大鱼>2 小时前
多宠物家庭智能管理平台:云端架构与多设备协同实战
python·算法·iot·宠物
To_OC2 小时前
LC 22 括号生成:刷完这道题,我终于搞懂回溯剪枝了
javascript·算法·leetcode
To_OC3 小时前
LC 39 组合总和:回溯入门必刷题,我踩过的两个坑都在这了
javascript·算法·leetcode
数字杂技师3 小时前
每条推荐都很准,为什么我还是越刷越无聊?
算法
兰令水3 小时前
hot100【acm版】【2026.7.14打卡-java版本】
java·数据结构·算法·leetcode·面试
cpp_25013 小时前
P10098 [ROIR 2023] 地铁建设 (Day 2)
数据结构·c++·算法·贪心·二分答案·洛谷题解