Time Limit: 3 second
Memory Limit: 2 MB

【问题描述】

黑白棋游戏的棋盘由4*4方格阵列构成。棋盘的每一方格中放有1枚棋子,共有8枚白棋子和8枚黑棋子。这16枚棋子的每一种放置方案都构成一个游戏状态。在棋盘上拥有1条公共边的2个方格称为相邻方格。一个方格最多可有4个相邻方格。在玩黑白棋游戏时,每一步可将任何2个相邻方格中棋子互换位置。对于给定的初始游戏状态和目标游戏状态,编程计算从初始游戏状态变化到目标游戏状态的最短着棋序列。

【输入格式】

共有8行。前四行是初始游戏状态,后四行是目标游戏状态。每行4个数分别表示该行放置的棋子颜色,“0”表示白棋,“1”表示黑棋。

【输出格式】

第一行是着棋步数n,接下来n行,每行4个数分别表示该步交换棋子的两个相邻方格的位置。例如abcd表示将棋盘上(a,b)处的棋子与(c,d)处的棋子换位。

【输入样例】

    11110000111000101010010110100101

【输出样例】

    41222142432424344

【题解】

这题的难点在状态的判重上。需要用到二进制来表示棋子的状态。

首先,预处理出2^1->2^16;存在一个数组中。需要的时候直接访问即可。

然后把4行的棋子状态转变为一行。

如输入样例 起始状态为 1111000011100010;一共16个字符。

注意一开始的时候在字符串前加个空格。这样这串字符就从字符串的下标1开始了。

然后for (int i = 1;i <= 16;i++) sum +=two_n[i]*(s[i]-'0');

这样就把“二进制转化成10进制了”但注意真正的二进制转10进制需要逆序 且是从2^0开始的。

但我们只需要用二进制的思想存储状态就可以了。

然后bo[sum] = true,标记这个状态已经出现过。

然后进行广搜。

在广搜的时候不要把这段“十进制”转化成字符串。而是直接在这个“十进制”上进行操作。

我们在搜的时候只要考虑两个变换方向即向右和向下。因为向左和向右会重复。

同时我们要判断两个棋子颜色是否不同,如果颜色相同则移动毫无意义。

然后for(int i = 1;i <= 16;i++)

{ if ( i不是4的倍数)就可以向右移动

x = i+4;

如果x <=16就可以向下移动。其中x和i对应了需要移动的棋子 }

然后是变换的原理

比如

11100000000

我们要把第4个0变成1,只要加上2^4就可以了。

我们要把第2个1变成0,只要减去2^2就可以了。

具体的操作请看代码

【代码】

#include <cstdio>
#include <string>
#include <iostream>using namespace std;const int maxdl = 100000;struct ss
{int x1,y1,x2,y2;
};int two_n[17],f,t,team[maxdl],step[maxdl],pre[maxdl];
string s1,s2;
bool panchong[131079*2] = {0};
ss d_step[maxdl];void input_data(string & s1)
{s1 =" ";string ss;for (int i = 1;i <= 4;i++){getline(cin,ss);s1+=ss;       }
}void init() //先预处理出2的1次方到2的16次方
{two_n[0] = 1;for (int i = 1;i <= 16;i++)two_n[i] = two_n[i-1]*2;for (int i = 1;i <= 16;i++) //把“二进制转换成10进制 "f += (s1[i]-'0')*two_n[i];for (int i = 1;i <= 16;i++)t += (s2[i]-'0')*two_n[i];
}void output_ans(int temp) //用于递归输出方案。
{if (temp == 1) //如果前一个是头指针则结束。这是递归终点 return;output_ans(pre[temp]);printf("%d%d%d%d\n",d_step[temp].x1,d_step[temp].y1,d_step[temp].x2,d_step[temp].y2);
}void get_ans()
{int head = 0,tail =1;team[1] = f; //team数组用于存储以“十进制”存储的状态 step[1] = 0;if (f == t) //如果初始状态和末状态相同,则直接输出0 {printf("0");return;}panchong[f] = true; //标记这个状态已经找过 while (head != tail) {head++;int ff = team[head],ss = step[head]; //取出状态和步骤数 bool bo[17] = {0}; //用于“把十进制换成二进制” for (int i = 1;i <= 16;i++)if ( (ff & two_n[i]) > 0) //如果之前存过2^i次方,在这个伪10进制转换成2进制后//倒数第i+1位确实会变成1.所以和2^i进行与操作,如果这个位置上有棋子,最后结果会是大于0的。//比如有0011这样的情况。第3,4位为1,我们转换成的伪十进制是24;//之后我们要把这个棋子信息存进bo数组中//我们枚举i,i到了3,用2^3和24进行与运算//2^3的二进制是1000//24的二进制是11000 ,可以看到第4位都是1,所以我们判断i=3时,bo[i] = 1(true);//再枚举到4时//2^4的二进制是10000//24的二进制是11000 ,可以看到第5位都是1,所以我们判断i=4时,bo[i] = 1(true);//这种虽然和二进制转10进制的正确做法不同,但可以用这种“错误”的方法来存储状态//并且在用位运算进行“压缩”和“解压” //还有变换的例子。//还是上面的0011//伪十进制为24;//如果我们想把第3个1变成0就减去2^3.//就变成了16;//再用伪方法转换成二进制。就变成0001了。 bo[i] = true;for (int i = 1;i <= 16;i++){int temp,x;x= i + 4; //优先往下转换 if (x <= 16){if (bo[i] == (1-bo[x])) //如果那个位置的棋子颜色和当前枚举到的棋子颜色不同 {temp = ff; //対temp进行操作,不影响原数字 if (bo[x] == 0)    //用加减法分别把0变成1,1变成0(二进制上的1/0) temp += two_n[x];elsetemp-=two_n[x];if (bo[i] == 0)temp +=two_n[i];elsetemp-=two_n[i];if (!panchong[temp]) //变换完之后进行判重 {panchong[temp] = true;tail++;if ((i % 4) != 0) //这里要把一维坐标转换成二维的,注意几个能被4整除的数的判断即可 d_step[tail].x1 = (i/4) + 1;elsed_step[tail].x1 = i/4;d_step[tail].y1 = ((i-1) % 4) + 1;if ((x % 4)!=0)d_step[tail].x2 = (x/4) + 1;elsed_step[tail].x2 = x / 4;d_step[tail].y2 = ((x-1) % 4) + 1;                                            team[tail] = temp; //记录这个状态 step[tail] = ss+1;                   pre[tail] = head; //记录前一个状态是什么 (最后输出方案) if (temp == t){printf("%d\n",ss+1);temp = tail;output_ans(temp); //用递归输出答案 return;}}                                               }}                  if ( (i % 4) !=0) //如果不是最右边的数字 {x = i+1;if (bo[x] == (1-bo[i]))    //如果颜色和当前的不同 {temp = ff;if (bo[x] == 0)   //在temp上进行操作 temp += two_n[x];elsetemp-=two_n[x];if (bo[i] == 0)temp +=two_n[i];elsetemp-=two_n[i];if (!panchong[temp]) //如果之前没有找到过这个状态 {panchong[temp] = true;//进行判重                 tail++; //把这个步骤加入到队列当中 if ( (i%4) !=0) //把一维坐标转换成二维坐标 d_step[tail].x1 = (i/4) + 1;elsed_step[tail].x1 = i/4;d_step[tail].y1 = ((i-1) % 4) + 1;if ((x % 4) != 0)d_step[tail].x2 = (x/4) + 1;elsed_step[tail].x2 = x /4;d_step[tail].y2 = ((x-1) % 4) + 1;team[tail] = temp;step[tail] = ss+1;   //步骤数+1 pre[tail] = head;if (temp == t) //如果找到了目标状态 则停止。 {printf("%d\n",ss+1);temp =tail;output_ans(temp);return;}} }}}}
}int main()
{//freopen("F:\\rush.txt","r",stdin);input_data(s1);input_data(s2);init();get_ans();return 0;
}

转载于:https://www.cnblogs.com/AWCXV/p/7632365.html

【9801】黑白棋游戏相关推荐

  1. c语言大作业黑白棋,C语言编写黑白棋游戏源代码.doc

    C语言编写的黑白棋游戏源代码 /*3.3.4 源程序*/ #include "graphics.h" /*图形系统头文件*/ #define LEFT 0x4b00 /*光标左键值 ...

  2. 【Python案例】基于Pygame黑白棋游戏(附源码)

    有没有小火伴是特别喜欢玩五子棋的,我记得我初中是特别喜欢的.于是,我今天就用Python给大家写了一个黑白棋游戏.代码放在下面了. 01.绘制棋盘 Python学习交流Q群:906715085### ...

  3. c语言课程设计之黑白棋游戏,c语言课程设计黑白棋游戏.doc

    您所在位置:网站首页 > 海量文档 &nbsp>&nbsp学术论文&nbsp>&nbsp大学论文 c语言课程设计黑白棋游戏.doc26页 本文档一共被 ...

  4. html5怎么判断迷宫输赢,HTML5 实现黑白棋游戏|附代码

    2)初始化游戏界面 游戏开始时,init()对保存棋盘上的棋子信息的qizi数组初始化,同时在棋盘上显示初始的4个棋子. function init(){             initLevel( ...

  5. C++ 黑白棋游戏的实现

    时光荏苒..眨眼间半年过去了.半年间我的人生轨迹经历了重大的改变.我最终还是决定把我在去年暑假里实现的这个C++的黑白棋游戏发布在我的CSDN博客上.这或许是我写的最后一个C++程序了. 记得当时,7 ...

  6. 黑白棋游戏 (BFS + 位运算初步运用)

    题目描述   黑白棋游戏的棋盘由4×4方格阵列构成.棋盘的每一方格中放有1枚棋 子,共有8枚白棋子和8枚黑棋子.这16枚棋子的每一种放置方案都构成一个游戏状态.在棋盘上拥有1条公共边的2个方格称为相邻 ...

  7. P3084 黑白棋游戏

      P3084 黑白棋游戏 时间: 1000ms / 空间: 65536KiB / Java类名: Main 描述 黑白棋游戏的棋盘由4×4方格阵列构成.棋盘的每一方格中放有1枚棋子,共有8枚白棋子和 ...

  8. 基于Python的Reversi黑白棋游戏设计与开发

    摘 要 黑白棋是一个相当易学,而且很受欢迎的游戏.近年来,随着机器性能的提高和相关理论的完善,人工智能这一领域变得越来越重要,在实际生活中的运用也越来越广泛.为了学习简单的人工智能,我决定用Pytho ...

  9. c语言写的黑白棋游戏代码,C语言编写的黑白棋游戏源代码..doc

    C语言编写的黑白棋游戏源代码. C语言编写的黑白棋游戏/*3.3.4 源程序*/ #include "graphics.h" /*图形系统头文件*/ #define LEFT 0x ...

最新文章

  1. JS编程建议——7:小心保留字的误用
  2. python代码在哪里输入-请问一下这个python代码到底是哪里出了问题?
  3. ssm异常捕获和处理
  4. Unity WebGL 窗口自适应
  5. c++mfc编写实验_零基础学Windows窗口图形界面编程(不用MFC),菜鸟学完变身高手,敢与专业媲美...
  6. 简单实用的多线程学习实例
  7. 【SGU】SGU每日练1·Little shop of flowers【DP】
  8. CRM系统能否用好 究竟是谁说了算?
  9. python __init__.py
  10. JAVA--位移运算符详细分析【转载】
  11. Printer Processor 导致的一个问题
  12. tomcat部署项目启动采坑之UnknownHostException
  13. Java中的各种数据类型的转换
  14. 《深入理解Nginx》 学习笔记(一)
  15. 比较好用的Java模拟器,515最好的java模拟器
  16. 老板拖欠工资怎么办?
  17. 打印机无法打印测试页
  18. 计算机的运行英文表示,电脑一些英文表示什么格式
  19. VTK笔记-图形相关-圆锥体-vtkConeSoure类
  20. 精选汇总 | 开心一刻

热门文章

  1. 菜鸟补给站 - -Java 常见笔试题
  2. 组态王bitset用法_组态王中的函数 bitset ( var,bitno,onoff )这个函数的中 var 指的是离散变量_绘本戏剧答案_学小易找答案...
  3. 移动发送短信接口测试(1)
  4. 4-20mA电流两线制温湿度变送器工作原理
  5. Windows系统常用快捷键整理
  6. python算法工程师需要学什么_人工智能算法工程师与Python工程师有什么区别?
  7. 掌握这些电子书搜索技巧与工具,拥有读不尽的书,从此不再闹书荒
  8. 程序员小灰的漫画算法
  9. PHP学习(3)—在HTML中嵌入PHP
  10. 相片怎么做音乐相册?这些方法帮助你搞定