题目大意:给定一个大小为 4*4 的棋盘,分别有 7 个黑子、7 个白子和 2 个空位构成,求出至少需要移动多少步,才能使得四个相同的棋子共线。

题解:显然每一种棋盘的局面都是一个状态,因此需要采用状态压缩的搜索。总共的局面最多有4e7种,并且所给的内存足够开下哈希表。

需要注意的是,数据中有很多不是对称的情况,因此需要分别考虑先移动白子和黑子的情况,再取最小值,得到答案。

代码如下

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int maxn=5e7;
  4. const int inf=0x3f3f3f3f;
  5. const int dx[]={0,0,-1,1};
  6. const int dy[]={1,-1,0,0};
  7. //b->1 w->0 o->2
  8. char s[10];
  9. int state[5][5],mp[2][maxn],ans=inf,st;
  10. bool col[maxn]; //b->1 w->0
  11. int get_hash(int a[5][5]){
  12. int val=0;
  13. for(int i=1;i<=4;i++)
  14. for(int j=1;j<=4;j++)
  15. val=val*3+a[i][j];
  16. return val;
  17. }
  18. void get_state(int val){
  19. for(int i=1;i<=4;i++)
  20. for(int j=1;j<=4;j++)
  21. state[i][j]=val%3,val/=3;
  22. }
  23. void read_and_parse(){
  24. for(int i=1;i<=4;i++){
  25. scanf("%s",s+1);
  26. for(int j=1;j<=4;j++){
  27. if(s[j]=='B')state[i][j]=1;
  28. if(s[j]=='W')state[i][j]=0;
  29. if(s[j]=='O')state[i][j]=2;
  30. }
  31. }
  32. st=get_hash(state);
  33. }
  34. bool right(int x,int y,int cor){
  35. if(x<1||y<1||x>4||y>4||state[x][y]!=cor)return 0;
  36. return 1;
  37. }
  38. bool check(int a[5][5]){
  39. for(int i=1;i<=4;i++){
  40. if(a[i][1]==a[i][2]&&a[i][2]==a[i][3]&&a[i][3]==a[i][4])return 1;
  41. if(a[1][i]==a[2][i]&&a[2][i]==a[3][i]&&a[3][i]==a[4][i])return 1;
  42. }
  43. if(a[1][1]==a[2][2]&&a[2][2]==a[3][3]&&a[3][3]==a[4][4])return 1;
  44. if(a[1][4]==a[2][3]&&a[2][3]==a[3][2]&&a[3][2]==a[4][1])return 1;
  45. return 0;
  46. }
  47. void solve(int cor){
  48. queue<int> q;
  49. q.push(st),mp[cor][st]=1,col[st]=cor;
  50. while(q.size()){
  51. int u=q.front();q.pop();
  52. get_state(u);
  53. if(check(state)){ans=min(ans,mp[cor][u]-1);return;}
  54. for(int i=1;i<=4;i++)for(int j=1;j<=4;j++)if(state[i][j]==2){
  55. for(int k=0;k<4;k++){
  56. int nx=i+dx[k],ny=j+dy[k];
  57. if(!right(nx,ny,col[u]))continue;
  58. swap(state[i][j],state[nx][ny]);
  59. int v=get_hash(state);
  60. if(!mp[cor][v])mp[cor][v]=mp[cor][u]+1,col[v]=col[u]^1,q.push(v);
  61. swap(state[i][j],state[nx][ny]);
  62. }
  63. }
  64. }
  65. }
  66. int main(){
  67. read_and_parse();
  68. solve(1);solve(0);
  69. printf("%d\n",ans);
  70. return 0;
  71. }

【codevs1004】四子连棋 状压bfs的更多相关文章

  1. 【宽度优先搜索】神奇的状态压缩 CodeVs1004四子连棋

    一.写在前面 其实这是一道大水题,而且还出在了数据最水的OJ上,所以实际上这题并没有什么难度.博主写这篇blog主要是想写下一个想法--状态压缩.状态压缩在记录.修改状态以及判重去重等方面有着极高的( ...

  2. codevs1004四子连棋[BFS 哈希]

    1004 四子连棋   时间限制: 1 s   空间限制: 128000 KB   题目等级 : 黄金 Gold   题目描述 Description 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗 ...

  3. codevs1004四子连棋

    1004 四子连棋  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold     题目描述 Description 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白 ...

  4. 迭代加深搜索[codevs1004 四子连棋]

    迭代加深搜索 一.算法简介 迭代加深搜索是在速度上接近广度优先搜索,空间上和深度优先搜索相当的搜索方式.由于在使用过程中引入了深度优先搜索,所以也可以当作深度优先搜索的优化方案. 迭代加深搜索适用于当 ...

  5. codevs1004 四子连棋

    题目描述 Description 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向上下左右四个方向移动到相邻的空格,这叫行棋一步,黑白双 ...

  6. codevs 1004 四子连棋 BFS、hash判重

    004 四子连棋 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold       题目描述 Description 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋 ...

  7. 【洛谷 P2346】四子连棋(状态压缩,搜索)

    其实这题可以直接二进制状压做,1表示黑棋,0表示白棋,另外记录下2个空点的位置就行了. 具体看代码(冗长): #include <iostream> #include <cstdio ...

  8. Codevs p1004 四子连棋

                          四子连棋 题目描述 Description 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向 ...

  9. P2346 四子连棋

    P2346 四子连棋 迭代加深++ 题意描述 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向上下左右四个方向移动到相邻的空格,这叫行棋 ...

随机推荐

  1. 我就骂你了,我tm还想打你呢

    从地铁出来,一男的抽烟走在我前面,走了一路闻了一路二手烟. 进门,一个园区的,我直接骂了一句:caoni妈的 这哥们瞪着我,我也瞪着他 你骂我干什么 我闻了一路子二手烟 你可以走前面啊 我不走啊 我不 ...

  2. TRIO-basic指令--九九乘法表demo

    在路上闲的没事,想到之前自己用别的语言实现乘法口诀表,于是来了兴趣用TRIO-basic试一下,挺简单的一段代码,大家看看就好. ' TRIO-basic '实现乘法口诀表 定义两个整型的局部变量 D ...

  3. PAT甲题题解-1129. Recommendation System (25)-排序

    博主欢迎转载,但请给出本文链接,我尊重你,你尊重我,谢谢~http://www.cnblogs.com/chenxiwenruo/p/6789819.html特别不喜欢那些随便转载别人的原创文章又不给 ...

  4. Linux内核分析——ELF文件格式分析

    ELF文件(目标文件)格式主要三种: 1)可重定向文件:文件保存着代码和适当的数据,用来和其他的目标文件一起来创建一个可执行文件或者是一个共享目标文件.(目标文件或者静态库文件,即linux通常后缀为 ...

  5. Linux内核读书笔记第六周

    主要内容: 什么是调度 调度实现原理 Linux上调度实现的方法 调度相关的系统调用 什么是调度 现在的操作系统都是多任务的,为了能让更多的任务能同时在系统上更好的运行,需要一个管理程序来管理计算机上 ...

  6. CI框架在辅助函数中使用配置文件中的变量

    问题: 现有一个自定义的辅助函数,想要获取配置文件中的配置项(配置文件路径为application/config/config.php) 分析: 辅助函数并不是定义在一个class中,而是很多个可供外 ...

  7. Hot code replace (HCR)

    https://wiki.eclipse.org/FAQ_What_is_hot_code_replace%3F https://zhidao.baidu.com/question/195505558 ...

  8. C++的内存分区

    C++的内存划分为栈区.堆区.全局区/静态区.字符串常量和代码区. 栈区 由系统进行内存的管理. 主要存放函数的参数以及局部变量.在函数完成执行,系统自行释放栈区内存,不需要用户管理.整个程序的栈区的 ...

  9. git常用命令及用法小计

    git init 初始化一个本地git仓库repository git status 查看状态 git add <file> 将工作区修改加到暂存区(stage) git commit - ...

  10. JavaScript——闭包机制

    闭包机制是JavaScript的重点和难点,本文希望能帮助大家轻松的学习闭包 一.什么是闭包? 闭包就是可以访问另一个函数作用域中变量的函数.下面列举出常见的闭包实现方式,以例子讲解闭包概念 func ...