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++的更多相关文章

  1. poj—1753 (DFS+枚举)

                                                                                                        ...

  2. 【dfs基础讲解及例题】

    定义 DFS(Depth-First-Search)深度优先搜索算法,是搜索算法的一种. 接下来因为懒得去找大段大段深奥的材料 所以就是一些个人的理解. 所谓深搜,是相对于广搜(只是第一篇)来说的.深 ...

  3. POJ 1753 位运算+枚举

    题意: 给出4*4的棋盘,只有黑棋和白棋,问你最少几步可以使棋子的颜色一样. 游戏规则是:如果翻动一个棋子,则该棋子上下左右的棋子也会翻一面,棋子正反面颜色相反. 思路: 都是暴搜枚举. 第一种方法: ...

  4. poj-3279 poj-1753(二进制枚举)

    题目链接:http://poj.org/problem?id=3279 题目大意: 有一个m*n的棋盘(1 ≤ M ≤ 15; 1 ≤ N ≤ 15),每个格子有两面分别是0或1,每次可以对一个格子做 ...

  5. [UOJ266]Alice和Bob又在玩游戏

    [UOJ266]Alice和Bob又在玩游戏 Tags:题解 作业部落 评论地址 TAG:博弈 题意 不同于树的删边游戏,删掉一个点删去的是到根的路径 题解 这题只和计算\(SG\)有关,博弈的有关内 ...

  6. POJ1753 Flip Game(位运算+暴力枚举)

    Flip game is played on a rectangular 4x4 field with two-sided pieces placed on each of its 16 square ...

  7. 【题解】射击-C++

    Description 不难发现,豆豆能从很多事情中去思考数学,于是豆豆父母决定让他去练习射击,这是项需要集中注意力的运动,相信 能够让豆豆暂时脱离数学.学习射击的第一天就让豆豆产生 了浓厚的兴趣,射 ...

  8. 1753 -- Flip Game

    Flip Game Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 48663   Accepted: 20724 Descr ...

  9. POJ 1753. Flip Game 枚举or爆搜+位压缩,或者高斯消元法

    Flip Game Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 37427   Accepted: 16288 Descr ...

随机推荐

  1. UWP中String 转为Path Data

    定义方法: Geometry PathMarkupToGeometry(string pathMarkup) { string xaml = "<Path " + " ...

  2. Linux kernel version dirty

    在我们使用git来管理Linux Kernel的时候,在编译的时候会在你的kernel version加上git commit number 有时候还会出现dirty字样,字面意思是内核被污染的意思. ...

  3. window8 飘带与页面切换效果

    演示效果如下 用鼠标点击滑动试试就能看到效果了 ^_^ iscroll 不仅可以做到自然滚动条的效果,看官方文档还可以用来做页面切换的效果,很好很强大. 所以我结合流行的飘带元素做了个简单的例子.. ...

  4. acl_cpp 的编译与使用

    注:因为现在 acl_cpp 已经合并进 acl 项目中,本文仅是介绍了老版本的 acl_cpp 的编译过程,新版本的介绍及编译请参考:acl 框架库简介. acl_cpp 是基于 acl 为基础开发 ...

  5. 使用VS2010再装VS2013不用再烦恼不兼容

    某些同事有时在开发过程中出现这么个问题,在使用js直接异步调用类库时,弹出错误类库不存在或者没有定义等,类似问题,这个时候可能你正在绞尽脑汁的去解决问题,明明问题不大,为什么安装VS2013后就不能打 ...

  6. hdu4633_Polya定理

    典型的Polya定理,还算比较简单,比赛的时候知道是Polya定理但是根本没留出时间去搞,有点小遗憾. 思路:根据Burnside引理,等价类个数等于所有的置换群中的不动点的个数的平均值,根据Poly ...

  7. Laravel5.x的php artisan migrate数据库迁移创建操作报错SQLSTATE[42000]解决

    Laravel5.x运行迁移命令创建数据表:php artisan migrate报错. Illuminate\Database\QueryException  : SQLSTATE[42000]: ...

  8. java中Array和ArrayList区别

    1)精辟阐述:可以将 ArrayList想象成一种“会自动扩增容量的Array”. 2)Array([]):最高效:但是其容量固定且无法动态改变:     ArrayList:  容量可动态增长:但牺 ...

  9. UTM (Urchin Tracking Module) codes

    UTM Codes are a great way to see the results of your offline marketing In today’s day and age, we ar ...

  10. jvm异常记录

    1.如果出现java.lang.OutOfMemoryError: Java heap space异常.原因:Java虚拟机的堆内存不够. 具体如下:                a.Java虚拟机 ...