您的位置:首页 > 其它

搜索 HOJ 1736 A Game on the Chessboard

2014-02-06 11:34 417 查看


A Game on the Chessboard

My Tags  (Edit)
 Source : CEOI
1999
 Time limit : 1 sec Memory limit : 32 M
Submitted : 26, Accepted :
20

On the chessboard of size 4x4 there are 8 white and 8 black stones, i.e. one stone on each field. Such a configuration of stones is called a game position. Two stones are adjacent if they are on fields with a common side (i.e. they are adjacent in either horizontal
or vertical direction but not diagonal). It means that each stone has at most 4 neighbours. The only legal move in our game is exchanging any two adjacent stones. Your task is to find the shortest sequence of moves transforming a given starting game position
into a given final game position.

Input

The starting game position is described in the first 4 lines of input. There are 4 symbols in each line, which define the colour of each stone in the row from the left to the right. The lines describe the rows of the chessboard from the top to the bottom. Symbol
`0' means a white stone and symbol `1' a black one. There is no space symbol separating the symbols in the line. The fifth line is empty. The next 4 following lines describe the final game position in the same way.

Output

The first line of output contains the number of the moves. The following lines describe the sequence of moves during the game. One line describes one move and it contains 4 positive integers R_1 C_1 R_2 C_2 separated by single spaces. These are the coordinates
of the adjacent fields for the move, i.e. fields [R_1,C_1] and [R_2,C_2], where R_1 (or R_2) is the number of the row and C_1 (or C_2) is the number of the column. The rows on the chessboard are numbered from 1 (top row) to 4 (bottom row) and the columns are
numbered from 1 (the leftmost column) to 4 (the rightmost one) as well (i.e. the coordinates of the left upper field are [1,1]). If there are multiple shortest sequences of moves transforming the starting position to the final position, you can output any
one of them.

Sample Input
1111
0000
1110
0010

1010
0101
1010
0101


Sample Output
4
1 2 2 2
1 4 2 4
3 2 4 2
4 3 4 4


题意:有一个棋盘,上面放了黑色和白色两种颜色的棋子,一次只能交换相邻两个位置的棋子,然后给出起始状态和目的状态,问最少能经过多少步到达,并且给出具体的操作。

思路:宽搜就行了,如果单向能过就单向搜就行了,如果不过就双向。由于只有16个位置,所以状态数为2^16,完全可以把棋盘看成一个int进行判重。然后记录步骤的时候我们用16bit表示棋盘状态,用8bit表示操作,因为操作是R1,C1,R2,C2 其中它们都是[1,4]那么两位就能表示一个数了,所以4个数字只需要8bit,我们用低8位表示操作,高16位表示棋盘状态。具体的操作可以看代码。

代码:
#include<iostream>
#include<stdio.h>
#include<cstring>
#include<string.h>
#include<queue>
using namespace std;
#define LL long long

int d[1<<16|1] , s , t , now;
int pre[1<<16|1];
int Move[2][4] = { { -1 , 0 , 1 , 0 } , { 0 , 1 , 0 , -1 } };
char buffer[10];

int row(int st)
{
return st / 4;
}

int column(int st)
{
return st % 4;
}

int to_loc(int r,int c)
{
return r*4+c;
}

bool inRange(int r,int c)
{
if (r < 0 || r >= 4 || c <0 || c >= 4) return false;
return true;
}

void init()
{
memset(pre,-1,sizeof(pre));
memset(d,-1,sizeof(d));
}

void input()
{
s = t = 0;
int base = 1;
for (int j = 0 ; j < 4 ; ++j)
{
if (buffer[j]=='1') s += base;
base *= 2;
}
for (int i = 1 ; i < 4 ; ++i)
{
scanf("%s",buffer);
for (int j = 0 ; j < 4 ; ++j)
{
if (buffer[j]=='1') s += base;
base *= 2;
}
}
base = 1;
for (int i = 0 ; i < 4 ; ++i)
{
scanf("%s",buffer);
for (int j = 0 ; j < 4 ; ++j)
{
if (buffer[j]=='1') t += base;
base *= 2;
}
}
}

void output(int cur)
{
if (cur==s) return;
output(pre[cur]>>8);
printf("%d %d %d %d\n",(pre[cur]>>6&3)+1,(pre[cur]>>4&3)+1,(pre[cur]>>2&3)+1,(pre[cur]&3)+1);
}

void solve()
{
queue<int> q;
q.push(s);
d[s] = 0;
while (q.size())
{
int st = q.front(); q.pop();
if (st==t) break;
for (int r = 0 ; r < 4 ; ++r)
{
for (int c = 0 ; c < 4 ; ++c)
{
for (int i = 0 ; i < 4 ; ++i)
{
now = st;
int rr = r+Move[0][i];
int cc = c+Move[1][i];
if (!inRange(rr,cc)) continue;
int k1 = to_loc(r,c);
int k2 = to_loc(rr,cc);
int tmp = ((1<<k2&now)>>k2<<k1)+((1<<k1&now)>>k1<<k2);
now -= (1<<k1&now)+(1<<k2&now);
now += tmp;
if (d[now]==-1)
{
d[now] = d[st]+1;
q.push(now);
pre[now] = (st<<8)+(r<<6)+(c<<4)+(rr<<2)+cc;
}
}
}
}
}
printf("%d\n",d[t]);
output(t);
}

int main()
{
while (scanf("%s",buffer)==1)
{
init();
input();
solve();
}
}


 

 

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: