题目链接

这道题和俄罗斯方块很像

很明显,我们可以看出这是一个dfs,但是,我们需要几条剪枝:

1.如果只剩下1个或2个同样颜色的方块,那么直接退出

2.相同的块不用交换

3.注意优先性,优先左边换右边

但是这题就这么样就完了吗

显然,并没有这么简单:剪枝清楚了,你确定就能写出来吗(这是我写过最长的dfs)

接下来讲一下我的程序架构:

init函数:输入,存储数据

fall函数:模拟方块下落

printans函数:输出答案

clear函数:清除棋盘

isempty函数:判断是否为空

judge函数:剪枝1

dfs函数:搜索

下面是代码,看不懂上面的话,代码里也有注释

 #include <bits/stdc++.h>
using namespace std; const int N = ;
const int M = ; int maxstep, chess[N][M];
int cnt[];
int answer[][]; void init()
{
cin>>maxstep;
for(int i=; i<N; i++)
{
int j=,x;
cin>>x;
while(x!=)
{
chess[i][j]=x;
j++;
cin>>x;
}
}
} void fall() //清除后方块下落
{
for(int i=; i<N; i++)
for(int j=; j<M; j++)
{
if(chess[i][j]!=)
continue;
int k;
for(k=j+; k<M; k++)
if(chess[i][k]!=)
{
swap(chess[i][j],chess[i][k]);
break;
}
if(k==M)
break;
}
} void printans() //输出
{
for(int i=; i<maxstep; i++)
printf("%d %d %d\n",answer[i][],answer[i][],answer[i][]);
return;
} bool clear() //清除棋盘
{
bool empty[N][M];
memset(empty,false,sizeof(empty));
for(int i=; i<N-; i++)
for(int j=; j<M; j++)
if(chess[i][j]!= && chess[i][j]==chess[i+][j]
&& chess[i+][j]==chess[i+][j]) {
empty[i][j]=empty[i+][j]=empty[i+][j]=true;
} for(int i=; i<N; i++)
for(int j=; j<M-; j++)
if(chess[i][j]!= && chess[i][j]==chess[i][j+]
&& chess[i][j+]==chess[i][j+]) {
empty[i][j]=empty[i][j+]=empty[i][j+]=true;
} bool res=false;
for(int i=; i<N; i++)
for(int j=; j<M; j++)
if(empty[i][j])
{
chess[i][j]=;
res=true;
}
return res;
} bool isempty() // 判断棋盘是否为空
{
for(int i=; i<N; i++)
for(int j=; j<M; j++)
if(chess[i][j]!=)
return false;
return true;
} bool judge() //判断是否有一种颜色的块数量为1或2
{
memset(cnt,,sizeof(cnt));
for(int i=; i<N; i++)
for(int j=; j<M; j++)
cnt[chess[i][j]]++;
for(int i=; i<=; i++)
if(cnt[i]==||cnt[i]==)
return false;
return true;
} bool dfs(int step) //搜索
{
if(isempty()) //发现一组解
{
printans();
return true;
}
if(step>=maxstep || !judge()) //剪枝与结束条件
return false; int now[N][M]; // 记录当前状态,回溯时候用
for(int i=; i<N; i++) //复制棋盘
for(int j=; j<M; j++)
now[i][j]=chess[i][j]; for(int i=; i<N; i++)
for(int j=; j<M; j++) //枚举每一个方块
{
//右移
if(i!=N- && chess[i][j]!= && chess[i][j]!=chess[i+][j])
{
swap(chess[i][j], chess[i+][j]);
answer[step][]=i;
answer[step][]=j;
answer[step][]=;
fall();
while(clear())
fall();
if(dfs(step+))
return true;
} for(int k1=; k1<N; k1++)
for(int k2=; k2<M; k2++)
chess[k1][k2]=now[k1][k2]; //左移
if(i!= && chess[i][j]!= && chess[i-][j]==)
{
swap(chess[i][j], chess[i-][j]);
answer[step][]=i;
answer[step][]=j;
answer[step][]=-;
fall();
while(clear())
fall();
if(dfs(step+))
return true;
} for(int k1=; k1<N; k1++)
for(int k2=; k2<M; k2++)
chess[k1][k2]=now[k1][k2];
}
return false;
} /*
搜索+剪枝
剪枝原则:
1,交换两个相同颜色的块没有意义。
2,如果一种颜色的块数量为1或2,则当前局面无解。
3,因为要求字典序最小的解,所以一个块仅当左边为空时尝试左移
(若左面有方块,那么在搜i-1列时将其右移,和在i列时左移是等效的,故可以剪枝)
*/
int main()
{
ios::sync_with_stdio(false);
cin.tie(); init();
if(!dfs())
cout<<-<<endl;
return ;
}

补充:说到俄罗斯方块,我又想起来USACO的这道题,有兴趣的同学可以去做做

洛古 P1312 Mayan游戏(dfs+剪枝)的更多相关文章

  1. 洛谷P1312 Mayan游戏

    P1312 Mayan游戏 题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他 ...

  2. [NOIP2011] 提高组 洛谷P1312 Mayan游戏

    题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.游戏通关是指在规定 ...

  3. 洛谷 P1312 Mayan游戏

    题解:搜索+模拟 剪枝: 最优性剪枝:x从小到大,y从小到大,第一次搜到的就是字典序最小 的最优解. 最优性剪枝:把一个格子和左边格子交换,和左边格子和右边格 子交换是等价的,显然让左边格子和右边交换 ...

  4. Luogu P1312 Mayan游戏(搜索)

    P1312 Mayan游戏 题意 题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个\(7\)行\(\times 5\)列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必 ...

  5. [题目] Luogu P1312 Mayan游戏

    题面 题目描述 $ Mayan puzzle $是最近流行起来的一个游戏.游戏界面是一个 \(7行 \times 5列\)的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放 ...

  6. 洛谷 1312 Mayan游戏——暴搜+剪枝

    题目:https://www.luogu.org/problemnew/show/P1312 自己写了很久.又T又WA的. 发现对题理解有误.改完后应该只有T了,但还是T的. 自己写了许多剪枝,很鸡肋 ...

  7. P1312 Mayan游戏

    题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.游戏通关是指在规定 ...

  8. [luogu P1312]Mayan游戏

    其实就是一道锻炼码力的简单题-- 看到题目中的\(0<x\leqslant 5\)也就知道是爆搜了吧( 我们仿照写游戏的方法多写几个函数,能够有效降低错误率(确信 我们写出大致的搜索流程来: 如 ...

  9. [洛谷P1731][NOI1999]生日蛋糕(dfs)(剪枝)

    典型的深搜+剪枝策略 我们采用可行性剪枝.上下界剪枝.优化搜索顺序剪枝.最优性剪枝的方面来帮助我们进行剪枝. 也许有人还不知道剪枝,那我就弱弱地为大家补习一下吧qwq: .优化搜索顺序: 在一些搜索问 ...

随机推荐

  1. 某某项目SDV软件测试报告范例

    说明:本范例为符合CMMI 5级要求的范例 Prepared by 拟制 小张 Date 日期 2008-04-09 Reviewed by 评审人 小丽.小王.小李.小莉.小三.小四.小猪.小猫.小 ...

  2. WiFi产生电磁辐射或让人想去自杀

    随着互联网在生活中的地位越来越重要,WiFi作为一种无线连接方式给了用户极大的便捷,然而有一部分科学家提出WiFi产生的电磁反应会对人的健康受到影响.面对这种说法,我们一直以为是专家在危言耸听,但是如 ...

  3. linux下查找文件及查找包含指定内容的文件常用命令

    whereis <程序名称> 查找软件的安装路径-b 只查找二进制文件-m 只查找帮助文件-s 只查找源代码-u 排除指定类型文件-f 只显示文件名-B <目录> 在指定目录下 ...

  4. 解决sendmail发送邮件慢的问题

    sendmail默认会先监听本机的邮件服务,如果本机邮件服务访问不了,在访问其他的邮件服务器 自己测试将本机主机名(通过hostname命令查看)从/etc/hosts中删除,发送邮件的速度就非常快了 ...

  5. 达拉草201771010105《面向对象程序设计(java)》第四周学习总结

    实验四类与对象的定义及使用 实验时间 2018-9-20 第一部分:理论知识 1.类与对象概念 (1)类是具有相同属性和方法的一类事物的抽象,是构造对象的模板或蓝图,由类构造对象的过程称为创建类的实例 ...

  6. win10安装LoadRunner时,安装.net framwork组件报0x800F081F错误 解决办法

    一.报错原因 0x800F081F错误大多数是在安装软件时,系统无法联网自动下载安装. 经过各种排查及搜索解决方案,总结原因无非以下三种: 1.windows update被禁用. 2.电脑没有.ne ...

  7. tomcat服务器和http协议笔试题

    tomcat与web程序结构与Http协议与HttpUrlConnection 考查的知识点:tomcat服务器相关信息 1.下面关于tomcat服务器描述正确的是() (难度A) A. tomcat ...

  8. 组件化思路:以selection为例子,使用prop-types实现组件化控制,重用

    需求 书接上文,UI 积累之select section 这里又来两个需求了. 当我点击选择了option后,我应该看到的是我选择的option的内容 多例重用,即同样是个selection,我只是需 ...

  9. CSS+DIV自适应布局

    CSS+DIV自适应布局 1.两列布局(左右两侧,左侧固定宽度200px;右侧自适应占满) 代码如下: <!doctype html> <html> <head> ...

  10. JS对象之封装(二)

    JS 对象封装的常用方式 1.常规封装 function Person (name,age){ this.name = name; this.age = age; } Pserson.prototyp ...