洛谷P1312 Mayan游戏——dfs

本文详细解析了洛谷P1312题目,通过递归搜索结合剪枝优化的方法解决方块消除问题。重点介绍了状态转移、循环处理掉落与消除的过程以及回溯算法的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目: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;   
}

 

资源下载链接为: https://pan.quark.cn/s/22ca96b7bd39 在 IT 领域,文档格式转换是常见需求,尤其在处理多种文件类型时。本文将聚焦于利用 Java 技术栈,尤其是 Apache POI 和 iTextPDF 库,实现 doc、xls(涵盖 Excel 2003 及 Excel 2007+)以及 txt、图片等格式文件向 PDF 的转换,并实现在线浏览功能。 先从 Apache POI 说起,它是一个强大的 Java 库,专注于处理 Microsoft Office 格式文件,比如 doc 和 xls。Apache POI 提供了 HSSF 和 XSSF 两个 API,其中 HSSF 用于读写老版本的 BIFF8 格式(Excel 97-2003),XSSF 则针对新的 XML 格式(Excel 2007+)。这两个 API 均具备读取和写入工作表、单元格、公式、样式等功能。读取 Excel 文件时,可通过创建 HSSFWorkbook 或 XSSFWorkbook 对象来打开相应格式的文件,进而遍历工作簿中的每个 Sheet,获取行和列数据。写入 Excel 文件时,创建新的 Workbook 对象,添加 Sheet、Row 和 Cell,即可构建新 Excel 文件。 再看 iTextPDF,它是一个用于生成和修改 PDF 文档的 Java 库,拥有丰富的 API。创建 PDF 文档时,借助 Document 对象,可定义页面尺寸、边距等属性来定制 PDF 外观。添加内容方面,可使用 Paragraph、List、Table 等元素将文本、列表和表格加入 PDF,图片可通过 Image 类加载插入。iTextPDF 支持多种字体和样式,可设置文本颜色、大小、样式等。此外,iTextPDF 的 TextRenderer 类能将 HTML、
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值