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. /\B(?=(?:\d{3})+$)/g 一条令人费解的正则表达式

    网上浏览博客看到要用JavaScript正则表达式解决一个功能, 要在数字中间插入逗号, 用来表示书面的金额写法. JS代码是这样子的 let test1 = '1234567890' let for ...

  2. Ubuntu 搭建 GitLab 笔记

    简介 GitLab 社区版可以提供许多与 GitHub 相同的功能,且部署在属于自己的机器上,我们会因为网络及其他一些问题而不便使用 GitHub ,这时部署一个 GitLab 是最好的选择. 下载 ...

  3. 基于Monte Carlo方法的2048 A.I.

    2048 A.I. 在 stackoverflow 上有个讨论:http://stackoverflow.com/questions/22342854/what-is-the-optimal-algo ...

  4. Android 8通过startService引起crash问题

    Android 8.0 不再允许后台service直接通过startService方式去启动,否则就会引起IllegalStateException.解决方式: if (Build.VERSION.S ...

  5. 年度调查 看看 2016 年 Go 语言调查结果

    Go 语言官方博客公布了 2016 年 Go 语言使用调查. 在 3,595 名被调查者中,89% 称他们在工作中或工作之外用 Go 编程:63% 称他们的工作是 Web 开发,但只有 9% 的人只从 ...

  6. MISP版本嵌入式QT编译时出现mips-linux-gcc command not found

    configure的时候都没什么问题我的configure是:./configure -prefix /opt/qt-jz -xplatform qws/linux-mips-g++ -embedde ...

  7. JavaScript语言核心--词法结构

    编程语言的词法结构是一套基础性规则,用来描述如何使用这门语言来编写程序.作为语法的基础,它规定了诸如变量名是什么样的.怎么写注释,以及程序语言之间如何分隔等规则. 1. 字符集 JavaScript程 ...

  8. Google C++测试框架系列高级篇:第二章 让GTest学习打印自定义对象

    上一篇:更多关于断言的知识 原始链接:Teaching Google Test How to Print Your Values 词汇表 版本号:v_0.1 让GTest学习打印自定义对象 当一个断言 ...

  9. LeetCode : Given a string, find the length of the longest serial substring without repeating characters.

    Given a string, find the length of the longest serial substring without repeating characters. Exampl ...

  10. 基于ASP.NET的新闻管理系统(三)代码展示

    5.1.1栏目部分 增加栏目(addLanMu.aspx): <html xmlns="http://www.w3.org/1999/xhtml"> <head  ...