HDU1401(Solitaire)

Solitaire

Problem Description

Solitaire is a game played on a chessboard 8x8. The rows and columns of the chessboard are numbered from 1 to 8, from the top to the bottom and from left to right respectively.

There are four identical pieces on the board. In one move it is allowed to:

move a piece to an empty neighboring field (up, down, left or right),

jump over one neighboring piece to an empty field (up, down, left or right).
在这里插入图片描述
There are 4 moves allowed for each piece in the configuration shown above. As an example let’s consider a piece placed in the row 4, column 4. It can be moved one row up, two rows down, one column left or two columns right.
Write a program that:
reads two chessboard configurations from the standard input,
verifies whether the second one is reachable from the first one in at most 8 moves,
writes the result to the standard output.

Input

Each of two input lines contains 8 integers a1, a2, …, a8 separated by single spaces and describes one configuration of pieces on the chessboard. Integers a2j-1 and a2j (1 <= j <= 4) describe the position of one piece - the row number and the column number respectively. Process to the end of file.

Output

The output should contain one word for each test case - YES if a configuration described in the second input line is reachable from the configuration described in the first input line in at most 8 moves, or one word NO otherwise.

Sample Input

4 4 4 5 5 4 6 5
2 4 3 3 3 6 4 6

Sample Output

YES

思路

双向广搜的第一道题,虽然很早就知道有这么个玩意,思路也很清晰但是不怎么用,可能是大部分常见的题目都能单向搜过去吧。这道题的技巧还是很多的,最重要的是怎么对棋盘状态判重这个很重要,其次就是棋子有四个,开八维数组判重,但是四个棋子全排列有很多种坐标。这里就需要排序处理,按棋子坐标升序依次往八维数组里面放。其实也就是通过排序hash了,你也可以对四个棋子的全排列顺序进行标记。不过写的代码会很多。最好的标记就是按照棋子升序标记,这样就不会很麻烦。tbfs + sort排序,思路就是正向拓展四次,反向拓展四次,如果两个范围跑出来的圆圈能产生交点那么一定可以,如果tbfs跑出来的范围没有交点代表无法实现,这样就能避免内存消耗太大已经时间不理想的情况。细节看代码~~~~

//Accepted	1401	62MS	18264K	3657 B	G++
#include <iostream>
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
struct point{
	int x,y;
};
struct info{
	point a[4];
	int step;
}s,e;
bool map[10][10];
char v[8][8][8][8][8][8][8][8];
int dx[] = {1,-1,0,0};
int dy[] = {0,0,-1,1};
queue<info>q[2];
void clear_set()										
{
	memset(v,false,sizeof(v));
	while(!q[0].empty()){
		q[0].pop();
	}
	while(!q[1].empty()){
		q[1].pop();
	}
	memset(v,0,sizeof(v));
}
bool cmp(point s1,point s2)								//排序规则 
{
	if(s1.x == s2.x){
		return s1.y < s2.y;
	}
	else{
		return s1.x < s2.x;
	}
}
inline void set_map(info p)
{
	map[p.a[0].x][p.a[0].y] = true;
	map[p.a[1].x][p.a[1].y] = true;
	map[p.a[2].x][p.a[2].y] = true;
	map[p.a[3].x][p.a[3].y] = true;
}
inline void set_visited(info p,char x)					//设置标记 
{
	v[p.a[0].x][p.a[0].y][p.a[1].x][p.a[1].y][p.a[2].x][p.a[2].y][p.a[3].x][p.a[3].y] = x;
}
inline char get_visited(info p)							//获得标记值 
{
	return v[p.a[0].x][p.a[0].y][p.a[1].x][p.a[1].y][p.a[2].x][p.a[2].y][p.a[3].x][p.a[3].y];
}
inline bool check(int x,int y)							//边界检查 
{
	if(x >= 0 && x < 8 && y >=0 && y < 8){
		return true;
	}
	else{
		return false;
	}
}
int tbfs()
{
	set_visited(s,'1');
	set_visited(e,'2');
	s.step = 0;e.step = 0;
	q[0].push(s);q[1].push(e);
	info ptr,str;
	while(!q[0].empty() || !q[1].empty()){
		if(!q[0].empty()){
			ptr = q[0].front();q[0].pop();
			if(ptr.step >= 4){									//大于等于4步不再拓展 
				continue;
			}
			memset(map,false,sizeof(map));
			set_map(ptr);
			for(int i = 0;i < 4;i++){
				for(int j = 0;j < 4;j++){
					info p;
					memcpy(&p,&ptr,sizeof(info)); 
					p.a[i].x = ptr.a[i].x + dx[j];
					p.a[i].y = ptr.a[i].y + dy[j];
					if(!check(p.a[i].x,p.a[i].y)){				//走出边界跳掉 
						continue;
					}
					if(map[p.a[i].x][p.a[i].y]){				//相邻点不能走通,进行跳跃
						p.a[i].x += dx[j];
						p.a[i].y += dy[j];
						if(!check(p.a[i].x,p.a[i].y)){			//跳跃之后检查边界 
							continue;
						}
					}
					sort(p.a,p.a+4,cmp);
					if(get_visited(p) == '2'){
						return 1;
					}
					else if(get_visited(p) == '1'){
						continue;
					}
					p.step = ptr.step + 1;
					set_visited(p,'1');
					q[0].push(p);
				}
			}
		}
		if(!q[1].empty()){
			str = q[1].front();
			q[1].pop();
			if(str.step >= 4){
				continue;
			}
			memset(map,false,sizeof(map));
			set_map(str);
			for(int i = 0;i < 4;i++){
				for(int j = 0;j < 4;j++){
					info p;
					memcpy(&p,&str,sizeof(info)); 
					p.a[i].x = str.a[i].x + dx[j];
					p.a[i].y = str.a[i].y + dy[j];
					if(!check(p.a[i].x,p.a[i].y)){
						continue;
					}
					if(map[p.a[i].x][p.a[i].y]){
						p.a[i].x += dx[j];
						p.a[i].y += dy[j];
						if(!check(p.a[i].x,p.a[i].y)){
							continue;
						}
					}
					sort(p.a,p.a+4,cmp);
					if(get_visited(p) == '1'){
						return 1;
					}
					else if(get_visited(p) == '2'){
						continue;
					}
					set_visited(p,'2');
					p.step = str.step + 1;
					q[1].push(p);
				}
			}
		} 
	}
	return -1;						
}
int main()
{
	int x,y;
	while(~scanf("%d%d",&x,&y)){
		clear_set();
		s.a[0].x = x-1;s.a[0].y = y-1;
		for(int i = 1;i < 4;i++){
			scanf("%d%d",&x,&y);
			s.a[i].x = x-1;s.a[i].y = y-1;
		}
		for(int i = 0;i < 4;i++){
			scanf("%d%d",&x,&y);
			e.a[i].x = x-1;e.a[i].y = y-1;
		}
		sort(s.a,s.a+4,cmp);
		sort(e.a,e.a+4,cmp);
		int ans = tbfs();
		if(ans == -1){
			puts("NO");
		}
		else{
			puts("YES");
		}
	} 
	return 0;
}

愿你走出半生,归来仍是少年~

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值