题目链接

这道题和俄罗斯方块很像

很明显,我们可以看出这是一个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. linux公社大量免费的在线android资料

    2011年linux数据库的android在线分享 linux公社:开源公社             本文撰写:杨凯专属频道 下载如需密码,详见博客案例:点击我去查看密码 2011年9月12日 21: ...

  2. jQuery2.0.0版本以后不再支持ie8的原因

    在引用jQuery时,引用高版本的Jq会在IE8下报错,在网上查了一下,jq在2.0+的版本就已经放弃对ie8的支持了.之前没有仔细研究过jq版本,借此机会去看了一下jq版本的知识.一.如何查看jq的 ...

  3. 实现子数组和绝对值差最小 - Objective-C

    类似于背包问题,前提条件是数组全是正整数和0,先求和Sum,再从子数组中找出接近Sum/2的子数组 @interface TempState : NSObject @property (nonatom ...

  4. 论文笔记[Slalom: Fast, Verifiable and Private Execution of Neural Networks in Trusted Hardware]

    作者:Florian Tramèr, Dan Boneh [Standford University] [ICLR 2019] Abstract 为保护机器学习中隐私性和数据完整性,通常可以利用可信 ...

  5. Job for network.service failed because the control process exited with error code问题

    Job for network.service failed because the control process exited with error code问题 因为是克隆的,所以需要重新修改静 ...

  6. STL迭代器的使用、正向、逆向输出双向链表中的所有元素

    */ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...

  7. React之mockjs+sass+生命周期函数

    mdn W3C标准网站 运行sass cnpm i -D node-sass-chokidar npm-run-all rem单位设置 <script> //rem单位设置 documen ...

  8. go微服务框架kratos学习笔记十(熔断器)

    目录 go微服务框架kratos学习笔记十(熔断器) 什么是熔断 熔断器逻辑 kratos Breaker kratos 熔断逻辑 kratos熔断器使用说明 bladmaster client br ...

  9. shell 获取字符创长度&&识别当前使用的shell&&检查是否为超级用户

    1.获得字符串长度 可以使用下面的方法获得变量值得长度: length=${#value} 例如: [root@gameserver1 shell]# var=12345678 [root@games ...

  10. 7-44 jmu-python-区间数之和 (10 分)

    输入一个区间,计算里面能被3整除或被5整除的数和. 输入格式: 每行输入一个数据,代表区间左界和右界.区间包含左界和右界.数据必须是整数. 输出格式: 满足条件数和. 输入样例: 2 10 输出样例: ...