1. Description
  2. 有一个4*4的棋盘,放有16枚棋子。
  3. 每个棋子都是一面黑一面白,一开始有的黑面朝上,有的白面朝上。
  4. 下面是一个例子,这个例子用文字描述为:
  5. bwbw
  6. wwww
  7. bbwb
  8. bwwb
  9. 我们可以任选一个棋子,把它自己和它的相邻棋子(上下左右,如果有的话)翻面。
  10. 比如在例子中如果我们选第3行第1列的棋子翻面,布局就变成如下:
  11. bwbw
  12. bwww
  13. wwwb
  14. wwwb
  15. 题目
  16. 求出能把所有棋子都翻成白色或都黑色的最少的步数。
  17. Input
  18. 4行每行4个字符,可能是b(黑)或w(白)
  19. Output
  20. 一个数,最少步数。如果无解输出Impossible
  21. Sample Input
  22. bwbw
  23. wwww
  24. bbwb
  25. bwwb
  26. Sample Output
  27. 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函数:

  1. bool check()
  2. {
  3. for(int i=1;i<=4;i++)
  4. {
  5. for(int j=1;j<=4;j++)
  6. {
  7. if(mp[i][j]!=mp[1][1])return 0;
  8. }
  9. }
  10. return 1;
  11. }

翻面也可以暴力写出来:

  1. int dir[5][2]={{0,0},{0,1},{0,-1},{1,0},{-1,0}};
  2. void fan(int x,int y)
  3. {
  4. for(int i=0;i<5;i++)
  5. {
  6. int tx=x+dir[i][0],ty=y+dir[i][1];
  7. if(in(tx,ty))mp[tx][ty]=back(mp[tx][ty]);
  8. }
  9. }

顺便把判断越界的写好

  1. bool in(int x,int y)
  2. {
  3. return 1<=x&&x<=4&&1<=y&&y<=4;
  4. }

然后就是核心部分—dfs了。

先贴一个模板:

  1. void dfs()//参数用来表示状态
  2. {
  3. if(到达终点状态)
  4. {
  5. ...//根据题意添加
  6. return;
  7. }
  8. if(越界或者是不合法状态)
  9. return;
  10. if(特殊状态)//剪枝
  11. return ;
  12. for(扩展方式)
  13. {
  14. if(扩展方式所达到状态合法)
  15. {
  16. 修改操作;//根据题意来添加
  17. 标记;
  18. dfs();
  19. (还原标记);
  20. //是否还原标记根据题意
  21. //如果加上(还原标记)就是 回溯法
  22. }
  23. }
  24. }

1.参数

void dfs(int step,int x,int y)

2.终点状态

if(check()){...}

3.不合法状态

if(x==5)return;

4.剪枝

这道题不需要 awa

5.扩展方式

这道题的扩展方式和模板有点不一样,这个只分两种:翻或者是不翻,但是要注意的是,翻之前要给x,y打上标记,翻完了再取消标记,达到回溯的效果!

  1. fan(x,y);
  2. if(y==4)dfs(step+1,x+1,1);
  3. else dfs(step+1,x,y+1);
  4. fan(x,y);
  5. if(y==4)dfs(step,x+1,1);
  6. else dfs(step,x,y+1);
  7. return;

输入的时候最好把原图转换成01矩阵,方便后续操作awa

  1. for(int i=1;i<=4;i++)
  2. {
  3. for(int j=1;j<=4;j++)
  4. {
  5. cin>>ch;
  6. if(ch=='b')
  7. {
  8. mp[i][j]=1;
  9. }
  10. else mp[i][j]=0;
  11. }
  12. }

那个布尔类型的ok是来记是否有解的,如果没有就输出Impossible就可以了。

完整代码贴一下还是:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. char ch;
  4. int mp[5][5],/*01矩阵*/min_ans=0x3f3f3f3f,dir[5][2]={{0,0},{0,1},{0,-1},{1,0},{-1,0}};
  5. bool ok;
  6. int back/*反面*/(int x)
  7. {
  8. return (x+1)%2;
  9. }
  10. bool in(int x,int y)
  11. {
  12. return 1<=x&&x<=4&&1<=y&&y<=4;
  13. }
  14. bool check()
  15. {
  16. for(int i=1;i<=4;i++)
  17. {
  18. for(int j=1;j<=4;j++)
  19. {
  20. if(mp[i][j]!=mp[1][1])return 0;
  21. }
  22. }
  23. return 1;
  24. }
  25. void fan(int x,int y)
  26. {
  27. for(int i=0;i<5;i++)
  28. {
  29. int tx=x+dir[i][0],ty=y+dir[i][1];
  30. if(in(tx,ty))mp[tx][ty]=back(mp[tx][ty]);
  31. }
  32. }
  33. void dfs(int step,int x,int y)
  34. {
  35. if(check())
  36. {
  37. min_ans=min(min_ans,step);
  38. ok=1;
  39. return;
  40. }
  41. if(x==5)return;
  42. fan(x,y);
  43. if(y==4)dfs(step+1,x+1,1);
  44. else dfs(step+1,x,y+1);
  45. fan(x,y);
  46. if(y==4)dfs(step,x+1,1);
  47. else dfs(step,x,y+1);
  48. return;
  49. }
  50. int main()
  51. {
  52. for(int i=1;i<=4;i++)
  53. {
  54. for(int j=1;j<=4;j++)
  55. {
  56. cin>>ch;
  57. if(ch=='b')
  58. {
  59. mp[i][j]=1;
  60. }
  61. else mp[i][j]=0;
  62. }
  63. }
  64. dfs(0,1,1);
  65. if(!ok)
  66. {
  67. cout<<"Impossible"<<endl;
  68. }
  69. else cout<<min_ans<<endl;
  70. return 0;
  71. }

【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. C# 如何使用 Sql Server Compact 数据库

    Sql Server Compact Edition(简称SqlCE)是一个轻量级的数据库,对于放在客户机上的程序而有需要存储数据这样的环境,使用SqlCE再合适不过了.SqlCE可以通过在VS(Vi ...

  2. HTML 滚动条实现

    ##在对应的div中,添加overflow,固定高度为400px<div class="panel-body" style="height: 400px; over ...

  3. ASP.NET MVC视图

    前言 视图即是用户与Web应用程序的接口,用户通常会看到视图,然后在视图上进行交互,Web应用程序的视图通常是HTML格式. 首先了解控制器选择返回哪个视图的问题.新建一个项目,浏览到/Home/Ab ...

  4. MinGW 编译 libsndfile-1.0.25(只要有 MSYS,./configure make make install 就行了)

    最近做的一个项目需要读写 wav 文件.在网上找到 libsndfile 刚好满足我的需要.但是编译的时候遇到了点小麻烦,这里记录一下编译的过程,免得下次再编译时忘记了. 因为是在编译完成若干天后写的 ...

  5. Windows完成端口编程

    Windows完成端口编程目录一 基本概念二 OVERLAPPED数据结构三 完成端口的内部机制创建完成端口完成端口线程的工作原理线程间数据传递线程的安全退出 一 基本概念       设备---wi ...

  6. CrashRpt_v.1.4.2_vs2008_also_ok

    1.windows多线程程序release版崩溃记录工具,便于该如何查找错误. 2.此工具主要用来配置windbug工具,一种排查程序发布版本崩溃这种非常难处理的缺陷的方法,非常棒,amazing! ...

  7. MySQL批量更新一个字段的值为随机数

    $arr = []; $str = ''; for ($i=0; $i < 2660; ++$i) { $str .= " WHEN ".$i." THEN &qu ...

  8. spark streaming 接收kafka消息之四 -- 运行在 worker 上的 receiver

    使用分布式receiver来获取数据使用 WAL 来实现 exactly-once 操作: conf.set("spark.streaming.receiver.writeAheadLog. ...

  9. kubernetes实战篇之nexus oss服务器部署及基于nexus的docker镜像仓库搭建

    系列目录 Nexus oss仓库管理平台搭建 Nexus是一款仓库管理工具,支持Npm,bower,maven,nuget,apt,yum甚至docker,helm等各种仓库,说的通俗以下,就是私服镜 ...

  10. Nginx学习笔记---服务与集群

    一.集群 什么是集群 服务器架构集群:多台服务器组成的响应式大并发,高数据量访问的架构体系. 特点: (1)成本高 (2)能够降低单台服务器的压力,使用流量平均分配到多台服务器 (3)使网站服务架构更 ...