关于黑白棋游戏题解
焦祺 08-11-28
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Problem Description
黑白棋游戏的棋盘由4×4方格阵列构成。棋盘的每一方格中放有1枚棋子,共有8枚白棋子和8枚黑棋子。这16枚棋子的每一种放置方案都构成一个游戏状态。在棋盘上拥有1条公共边的2个方格称为相邻方格。一个方格最多可有4个相邻方格。在玩黑白棋游戏时,每一步可将任何2个相邻方格中棋子互换位置。对于给定的初始游戏状态和目标游戏状态,编程计算从初始游戏状态变化到目标游戏状态的最短着棋序列。
Input
包括若干组数据。第一行一个数n表示数据的组数。
每组数据共有8行。前四行是初始游戏状态,后四行是目标游戏状态。每行4个数分别表示该行放置的棋子颜色。“0”表示白棋;“1”表示黑棋。
Output
对应每组输入数据,输出如下结果:第一行是着棋步数n。接下来n行,每行4个数分别表示该步交换棋子的两个相邻方格的位置。例如,abcd表示将棋盘上(a,b)处的棋子与(c,d)处的棋子换位。
Sample Input
1
1111
0000
1110
0010
1010
0101
1010
0101
Sample Output
4
1222
1424
3242
4344
由于没有设定好数据的范围,开始的时候没有能够得出正确答案
后来设好了居然TLE了!!
我就知道会这样,不过,要用什么方法优化呢~~
【网上某种解题思路】
这应该是这套题中最简单的一道,是一道典型的广度优先搜索,解决此题的关键就在于对状态的记录。我们发现这个矩阵我们可以看成成一个16位的二进制数,而且不会有重复。所以我们可以把它转化成一个十进制数,然后我们可以开一个布尔数组,用来记录,下标对应的状态是否存在。接着我们发现,如果当前矩阵中的某个位置与目标状态相同,我们就不需要再对它进行移动。而我们的转移是与上、下、左、右进行交换,如果相同,交换显然是没有必要的,否则一定不会更优。这样就可以进一步减少状态。经过这些处理,对于这个4*4的矩阵就完全没有问题了。
当然,在具体处理时,我们也有着不同的方法。最简单的就是用整数矩阵,但是这个方法并不优。而根据标程,我们发现,其实用位运算进行处理效率会很高,另外用字符串效率也不错。
这样,我们就可以完美的解决了。
并且得到一高手提示:
C(16,8)=16!/8!/8! 种状态
也就是说总共只有 10000多种状态
可以直接用BFS搜索
1111 1111
0000 1111
1111 1111
1111 0000
对于左边的状态,它对应的数是 1111000011111111 看成二进制数
它的十进制是: 1<<15 + 1<<14 + 1<<13 + 1<<12 + 0<<11 + 0<<10 + ...
也就是 Sigma(a[i]<<i) !!
于是我在结点里添加了一个整型用于记录
这样在判重和find的时候会减少一部分时间
代码如下:(或有少许BUG)
#include <iostream>
using namespace std;
struct Node
{
int n;
bool p[4][4];
int last;
int sx,sy;
int dx,dy;
};
char a[4][4];
char b[4][4];
int dir[4][2] = { {-1,0},{0,-1},{0,1},{1,0}};
int counter;
Node start;
Node end;
Node state[15000];
int stateint[15000];
void bfs();
bool expand(Node& temp,int i,int j,int x,int y); //扩展结点
bool repeat(Node temp,int tail); //重复结点判断
bool finds(Node temp);//
void printpath(int tail);
void init();
void changetobit(Node& temp);
int main()
{
int i,j,t,bit;
scanf("%d",&t) ;
getchar();
while (t--)
{
bit = 15;start.n =0;
for (i=0;i<4;i++)
{
for (j=0;j<4;j++)
{
scanf("%c",&a[i][j]);
if(a[i][j] == '1')
{
start.p[i][j] = 1;
start.n += (1<<bit);
bit--;
}
else
{
start.p[i][j] = 0;
start.n += (0<<bit);
bit--;
}