【DFS练习】-翻棋子-C++
Description
有一个4*4的棋盘,放有16枚棋子。
每个棋子都是一面黑一面白,一开始有的黑面朝上,有的白面朝上。
下面是一个例子,这个例子用文字描述为:
bwbw
wwww
bbwb
bwwb
我们可以任选一个棋子,把它自己和它的相邻棋子(上下左右,如果有的话)翻面。
比如在例子中如果我们选第3行第1列的棋子翻面,布局就变成如下:
bwbw
bwww
wwwb
wwwb
题目
求出能把所有棋子都翻成白色或都黑色的最少的步数。
Input
4行每行4个字符,可能是b(黑)或w(白)
Output
一个数,最少步数。如果无解输出Impossible
Sample Input
bwbw
wwww
bbwb
bwwb
Sample Output
Impossible
这道题目是一道典型的 深搜。我们可以用3个参数记录一种状态:
step,x,y;
step即当前状态已经使用的步数,x,y,记当前正在考虑是否翻面的棋子的坐标,但是把x,y传到下一层有些麻烦…我们需要判断,如果y=4,那么就传给下一层(x+1,1),否则传给下一层(x,y+1),因为这里没有考虑到x是否越界,所以在dfs的拓展之前还要判断if(x==5)return;
代码实现。
代码实现一直是有些麻烦的事情,有些思路不及时打下来的话就可能逐渐消退。
根据题意,搜索的终点是所有棋子都朝向同一面,也就是任意棋子的朝向==第一颗的
那么很轻易可以写下check函数:
bool check()
{
for(int i=1;i<=4;i++)
{
for(int j=1;j<=4;j++)
{
if(mp[i][j]!=mp[1][1])return 0;
}
}
return 1;
}
翻面也可以暴力写出来:
int dir[5][2]={{0,0},{0,1},{0,-1},{1,0},{-1,0}};
void fan(int x,int y)
{
for(int i=0;i<5;i++)
{
int tx=x+dir[i][0],ty=y+dir[i][1];
if(in(tx,ty))mp[tx][ty]=back(mp[tx][ty]);
}
}
顺便把判断越界的写好
bool in(int x,int y)
{
return 1<=x&&x<=4&&1<=y&&y<=4;
}
然后就是核心部分—dfs了。
先贴一个模板:
void dfs()//参数用来表示状态
{
if(到达终点状态)
{
...//根据题意添加
return;
}
if(越界或者是不合法状态)
return;
if(特殊状态)//剪枝
return ;
for(扩展方式)
{
if(扩展方式所达到状态合法)
{
修改操作;//根据题意来添加
标记;
dfs();
(还原标记);
//是否还原标记根据题意
//如果加上(还原标记)就是 回溯法
}
}
}
1.参数
void dfs(int step,int x,int y)
2.终点状态
if(check()){...}
3.不合法状态
if(x==5)return;
4.剪枝
这道题不需要 awa
5.扩展方式
这道题的扩展方式和模板有点不一样,这个只分两种:翻或者是不翻,但是要注意的是,翻之前要给x,y打上标记,翻完了再取消标记,达到回溯的效果!
fan(x,y);
if(y==4)dfs(step+1,x+1,1);
else dfs(step+1,x,y+1);
fan(x,y);
if(y==4)dfs(step,x+1,1);
else dfs(step,x,y+1);
return;
输入的时候最好把原图转换成01矩阵,方便后续操作awa
for(int i=1;i<=4;i++)
{
for(int j=1;j<=4;j++)
{
cin>>ch;
if(ch=='b')
{
mp[i][j]=1;
}
else mp[i][j]=0;
}
}
那个布尔类型的ok是来记是否有解的,如果没有就输出Impossible就可以了。
完整代码贴一下还是:
#include<bits/stdc++.h>
using namespace std;
char ch;
int mp[5][5],/*01矩阵*/min_ans=0x3f3f3f3f,dir[5][2]={{0,0},{0,1},{0,-1},{1,0},{-1,0}};
bool ok;
int back/*反面*/(int x)
{
return (x+1)%2;
}
bool in(int x,int y)
{
return 1<=x&&x<=4&&1<=y&&y<=4;
}
bool check()
{
for(int i=1;i<=4;i++)
{
for(int j=1;j<=4;j++)
{
if(mp[i][j]!=mp[1][1])return 0;
}
}
return 1;
}
void fan(int x,int y)
{
for(int i=0;i<5;i++)
{
int tx=x+dir[i][0],ty=y+dir[i][1];
if(in(tx,ty))mp[tx][ty]=back(mp[tx][ty]);
}
}
void dfs(int step,int x,int y)
{
if(check())
{
min_ans=min(min_ans,step);
ok=1;
return;
}
if(x==5)return;
fan(x,y);
if(y==4)dfs(step+1,x+1,1);
else dfs(step+1,x,y+1);
fan(x,y);
if(y==4)dfs(step,x+1,1);
else dfs(step,x,y+1);
return;
}
int main()
{
for(int i=1;i<=4;i++)
{
for(int j=1;j<=4;j++)
{
cin>>ch;
if(ch=='b')
{
mp[i][j]=1;
}
else mp[i][j]=0;
}
}
dfs(0,1,1);
if(!ok)
{
cout<<"Impossible"<<endl;
}
else cout<<min_ans<<endl;
return 0;
}
【DFS练习】-翻棋子-C++的更多相关文章
- poj—1753 (DFS+枚举)
...
- 【dfs基础讲解及例题】
定义 DFS(Depth-First-Search)深度优先搜索算法,是搜索算法的一种. 接下来因为懒得去找大段大段深奥的材料 所以就是一些个人的理解. 所谓深搜,是相对于广搜(只是第一篇)来说的.深 ...
- POJ 1753 位运算+枚举
题意: 给出4*4的棋盘,只有黑棋和白棋,问你最少几步可以使棋子的颜色一样. 游戏规则是:如果翻动一个棋子,则该棋子上下左右的棋子也会翻一面,棋子正反面颜色相反. 思路: 都是暴搜枚举. 第一种方法: ...
- poj-3279 poj-1753(二进制枚举)
题目链接:http://poj.org/problem?id=3279 题目大意: 有一个m*n的棋盘(1 ≤ M ≤ 15; 1 ≤ N ≤ 15),每个格子有两面分别是0或1,每次可以对一个格子做 ...
- [UOJ266]Alice和Bob又在玩游戏
[UOJ266]Alice和Bob又在玩游戏 Tags:题解 作业部落 评论地址 TAG:博弈 题意 不同于树的删边游戏,删掉一个点删去的是到根的路径 题解 这题只和计算\(SG\)有关,博弈的有关内 ...
- POJ1753 Flip Game(位运算+暴力枚举)
Flip game is played on a rectangular 4x4 field with two-sided pieces placed on each of its 16 square ...
- 【题解】射击-C++
Description 不难发现,豆豆能从很多事情中去思考数学,于是豆豆父母决定让他去练习射击,这是项需要集中注意力的运动,相信 能够让豆豆暂时脱离数学.学习射击的第一天就让豆豆产生 了浓厚的兴趣,射 ...
- 1753 -- Flip Game
Flip Game Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 48663 Accepted: 20724 Descr ...
- POJ 1753. Flip Game 枚举or爆搜+位压缩,或者高斯消元法
Flip Game Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 37427 Accepted: 16288 Descr ...
随机推荐
- Android零基础入门第19节:Button使用详解
原文:Android零基础入门第19节:Button使用详解 Button(按钮)是Android开发中使用非常频繁的组件,主要是在UI界面上生成一个按钮,该按钮可以供用户单击,当用户单击按钮时,按钮 ...
- SignalR---DOTNET客户端
原文:SignalR---DOTNET客户端 这里面有用到异步的相关知识,本人前几篇文章也简单的提到. SignalR客户端要寄宿在.NET的客户端,必须安装Microsoft.AspNet.Sign ...
- C# 中使用OPenCV(Emgu)心得
原文:C# 中使用OPenCV(Emgu)心得 首先介绍一下自己的情况,2010年的3月份开始接触学习C#编程,之前C#和OpenCV都是零基础,由于全都是自学进度比较慢,中间也走了不少弯路.进过三个 ...
- 《译文》借助OCR和神经网络,用JavaScript识别验证码
昨天发现的了一段非常令人惊奇的JavaScript代码,是由ShaunF编写的automatically solves captchas,一个专门应用在Megaupload网站的Greasemonke ...
- GetParent、SetParent、MoveWindow - 获取、指定父窗口和移动窗口,IsChild - 判断两个窗口是不是父子关系
提示: SetParent 应该 Windows.SetParent, 因为 TForm 的父类有同名方法. //声明: {获取父窗口句柄} GetParent(hWnd: HWND): HWND; ...
- 长江存储32层3D NAND今年底准备好,预计2020年赶上世界前沿(有些ppt很精彩)
集微网消息(文/刘洋)2017年1月14日,首届IC咖啡国际智慧科技产业峰会暨ICTech Summit 2017在上海隆重举行.本次峰会以“匠心独运 卓越创‘芯’”为主题,集结了ICT产业领袖与行业 ...
- 浏览器引擎-phantomjs初次认识
最近没什么重要的任务,就抽空看了看项目组爬虫小组的代码,因为我们的爬虫主要是以python的scrapy框架为主,看起来比较方便.在看代码的时候看到一个叫phantomjs的东西,蛮新鲜的,就去问了下 ...
- 304902阿里巴巴Java开发手册1.4.0
转自官网 前言 <阿里巴巴Java开发手册>是阿里巴巴集团技术团队的集体智慧结晶和经验总结,经历了多次大规模一线实战的检验及不断完善,系统化地整理成册,回馈给广大开发者.现代软件行业的高速 ...
- 全自动Landsat影像温度反演软件开发
许久没有更新遥感类软件开发了,都有点生疏了,这一次我带来了一个老的算法,新的东西, 为什么这么说呢,我们知道Landat8.Landsat5等影像,单个影像去做温度反演,并没有什么太大的难度, 但是呢 ...
- Django 的路由系统
Django 的路由系统 Django 的路由系统 路由层 urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^$',views.ho ...