HDU 1401 Solitaire(bfs)

Solitaire

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 4522    Accepted Submission(s): 1369


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
思路:用一个 vis[8][8][8][8][8][8][8][8]数组来记录之前到达过的状态,之后就是一般的广搜。。。呕心沥血一整天,总是因为一些小的问题找了半天错误,以后还是得细心。。。
1.用一个bool ed[9][9]数组来保存最后应该到达的状态
2.用当前状态值通过check(node)函数与目标状态进行比对,比对成功bfs()结束
代码:
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
struct Node
{
   int step;
   int map[4][2];
   friend bool operator<(Node a,Node b)
   {
   	return a.step>b.step;
   }
};
bool vis[8][8][8][8][8][8][8][8];
int v[4][2]={-1,0,1,0,0,-1,0,1};
bool ed[9][9];
int st[4][2];
bool mark[9][9];
int maxx;
bool check(Node node)//检查是否达到目标状态 
{
	int count=0;
	for(int i=0;i<4;i++)
	{
		int x=node.map[i][0];
		int y=node.map[i][1];
//		printf("%d %d ",x,y);
		if(ed[x][y]) count++;
	}
//	printf(" count=%d\n",count);
	return count==4;
}

bool isVis(Node node)//判断是否出现过该状态 
{
	Node temp=node;
	int x1=temp.map[0][0];
	int y1=temp.map[0][1];
	int x2=temp.map[1][0];
	int y2=temp.map[1][1];
	int x3=temp.map[2][0];
	int y3=temp.map[2][1];
	int x4=temp.map[3][0];
	int y4=temp.map[3][1];
//	printf("x1 y1 x2 y2 x3 y3 x4 y4\n");
//	printf("%d %d %d %d %d %d %d %d\n",x1,y1,x2,y2,x3,y3,x4,y4);
	if(vis[x1][y1][x2][y2][x3][y3][x4][y4])
    return true;
    //若未出现,则对当前四个坐标所有的排列进行标记 
    vis[x1][y1][x2][y2][x3][y3][x4][y4]=true; 
    vis[x1][y1][x2][y2][x4][y4][x3][y3]=true;
    vis[x1][y1][x3][y3][x4][y4][x2][y2]=true;
    vis[x1][y1][x3][y3][x2][y2][x4][y4]=true;
 	vis[x1][y1][x4][y4][x2][y2][x3][y3]=true;
	vis[x1][y1][x4][y4][x3][y3][x2][y2]=true;
	vis[x2][y2][x1][y1][x3][y3][x4][y4]=true;
	vis[x2][y2][x1][y1][x4][y4][x3][y3]=true;
	vis[x2][y2][x3][y3][x1][y1][x4][y4]=true;
	vis[x2][y2][x3][y3][x4][y4][x1][y1]=true;
	vis[x2][y2][x4][y4][x1][y1][x3][y3]=true;
	vis[x2][y2][x4][y4][x3][y3][x1][y1]=true;
	vis[x3][y3][x1][y1][x2][y2][x4][y4]=true;
	vis[x3][y3][x1][y1][x4][y4][x2][y2]=true;
	vis[x3][y3][x2][y2][x1][y1][x4][y4]=true;
	vis[x3][y3][x2][y2][x4][y4][x1][y1]=true;
	vis[x3][y3][x4][y4][x1][y1][x2][y2]=true;
	vis[x3][y3][x4][y4][x2][y2][x1][y1]=true;
	vis[x4][y4][x1][y1][x2][y2][x3][y3]=true;
	vis[x4][y4][x1][y1][x3][y3][x2][y2]=true;
	vis[x4][y4][x2][y2][x1][y1][x3][y3]=true;
	vis[x4][y4][x2][y2][x3][y3][x1][y1]=true;
	vis[x4][y4][x3][y3][x1][y1][x2][y2]=true;
	vis[x4][y4][x3][y3][x2][y2][x1][y1]=true;
	return false;

}
int bfs()
{
	priority_queue<Node>q;
	Node node;
	node.step=0;
	for(int i=0;i<4;i++)//初始状态入队列 
	{
		node.map[i][0]=st[i][0];
		node.map[i][1]=st[i][1];
//		printf("st==%d %d\n",node.map[i][0],node.map[i][1]);
	}
	q.push(node);
	isVis(node);
	int flag=false; 
	while(!q.empty())
	{
	    if(maxx<q.size()) maxx=q.size(); 
		node=q.top();
		q.pop();
		if(check(node))  
		{	
//			printf("q.maxsize===%d\n",maxx);
//			printf("step==%d\n",step);
//			printf("%d %d %d %d %d %d %d %d\n",node.map[0][0],node.map[0][1],node.map[1][0],node.map[1][1],node.map[2][0],node.map[2][1],node.map[3][0],node.map[3][1]);
			return node.step; 
		}
		memset(mark,false,sizeof(mark));
		for(int k=0;k<4;k++) //以当前坐标值构建一个mark图 ,用于判断移动过后是否与其他三个位置重合 
		{
			mark[node.map[k][0]][node.map[k][1]]=true;
		}           
		for(int i=0;i<4;i++)//四个方向 
		{
			
			for(int j=0;j<4;j++)
			{  
			    Node temp=node; 
				int xx=node.map[j][0]+v[i][0];
				int yy=node.map[j][1]+v[i][1];
				int step=node.step+1;
				if(xx<0||xx>=8||yy<0||yy>=8) continue;//边界条件
				if(step>8) continue; 	
				if(mark[xx][yy]&&!mark[xx+v[i][0]][yy+v[i][1]])//当前方向下一位置有一个棋子,且棋子后为空格 
				{
				    	xx+=v[i][0];
				    	yy+=v[i][1];
				    	if(xx<0||xx>=8||yy<0||yy>=8) continue;
				    	
				}
				if(mark[xx][yy]) continue;//检测重合,判断棋子是否有重叠的情况 
				temp.map[j][0]=xx;
				temp.map[j][1]=yy;
				temp.step=step;
				if(check(temp)) return temp.step;//进入队列前与目标状态进行比对,若达到目标状态可以直接省去队列中现有的状态 
				if(isVis(temp)) continue;//判断之前是否出现过该状态 
		        q.push(temp);
			}
		}
	}
	return -1;
}
int main()
{
	memset(st,0,sizeof(st));
	
	int a,b;
//	freopen("out.doc","w",stdout);
  while(~scanf("%d%d",&st[0][0],&st[0][1]))
  {
  	//应为vis长度为8,输入值-1 
  		st[0][0]-=1;
  		st[0][1]-=1;
       for(int i=1;i<4;i++)
	   {
	   		scanf("%d%d",&a,&b);
	   		a--;
	   		b--;
	   		st[i][0]=a;
	   		st[i][1]=b;
	   }	
	   memset(ed,false,sizeof(ed));
	   for(int i=0;i<4;i++)
	   {
	  	 	scanf("%d%d",&a,&b);
	  	 	a--;
	  	 	b--;
	   		ed[a][b]=true;
	   }
	   memset(vis,false,sizeof(vis));   
	   int ans=-1;
	   maxx=0;
	   ans=bfs();
	   if(ans>=0)
	   	    printf("YES\n");
	   else  
	        printf("NO\n");
//	    printf("ans==%d  max==%d\n",ans,maxx);
	   	   
	   
  }	
} 
/*
4 4 4 5 5 4 6 5
2 4 3 3 3 6 4 6
1 2 2 3 3 4 4 5
1 3 2 4 3 5 4 6
1 1 1 1 1 1 1 1
2 2 2 2 2 2 2 2
4 4 4 5 5 4 6 5
4 4 4 5 5 4 6 5
1 1 1 2 1 3 1 4
3 1 3 2 3 3 3 4
*/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值