POJ 1915 Knight Moves 骑士遍历问题(跳马问题)

题目来源:http://poj.org/problem?id=1915

1、对于这道题,我首先根据宽度优先搜索的思想,自己独立写出代码。

#include<stdio.h>
int main()
{
	short l,n,x,y,x1,y1,k=0,x0,y0;
	int i,j,d,e;
	short c[301][301],a[90000][2];
	short bo;
	scanf("%d",&n);
  while (n--)
  {
	  k=0;
	scanf("%d",&l);
	scanf("%d%d%d%d",&x,&y,&x1,&y1);
	if ((x==x1)&&(y==y1)) printf("%d\n",k);
	else
	{	
		x0=x;y0=y;
		a[0][0]=x;a[0][1]=y;
		for (i=0;i<l;i++)
			for (j=0;j<l;j++)
				c[i][j]=0;
			i=0;d=0;e=-1;bo=1;
		while (bo)
		{
			k++;
			d=e+1;e=i;
			for (j=d;j<=e;j++)
			{
				x=a[j][0]+1;y=a[j][1]+2;
				if (x==x1&&y==y1) 
				{
					bo=0;
					break;
				}
				else if ((!c[x][y]&&x>=0&&x<l&&y>=0&&y<l)&&(x>x0-4||x>x1-4)&&(x<x0+4||x<x1+4)&&(y>y0-4||y>y1-4)&&(y<y0+4||y<y1+4))
				{   
					i++;
					a[i][0]=x;
					a[i][1]=y;
					c[x][y]=1;
				}
					x=a[j][0]+1;y=a[j][1]-2;
					if (x==x1&&y==y1) 
				{
					bo=0;
					break;
				}
            	else if ((!c[x][y]&&x>=0&&x<l&&y>=0&&y<l)&&(x>x0-4||x>x1-4)&&(x<x0+4||x<x1+4)&&(y>y0-4||y>y1-4)&&(y<y0+4||y<y1+4))
				{   
					i++;
					a[i][0]=x;
					a[i][1]=y;
					c[x][y]=1;
				}
					x=a[j][0]+2;y=a[j][1]+1;
					if (x==x1&&y==y1) 
				{
					bo=0;
					break;
				}
            	else if ((!c[x][y]&&x>=0&&x<l&&y>=0&&y<l)&&(x>x0-4||x>x1-4)&&(x<x0+4||x<x1+4)&&(y>y0-4||y>y1-4)&&(y<y0+4||y<y1+4))
				{   
					i++;
					a[i][0]=x;
					a[i][1]=y;
					c[x][y]=1;
				}
					x=a[j][0]+2;y=a[j][1]-1;
					if (x==x1&&y==y1) 
				{
					bo=0;
					break;
				}
            	else if ((!c[x][y]&&x>=0&&x<l&&y>=0&&y<l)&&(x>x0-4||x>x1-4)&&(x<x0+4||x<x1+4)&&(y>y0-4||y>y1-4)&&(y<y0+4||y<y1+4))
				{   
					i++;
					a[i][0]=x;
					a[i][1]=y;
					c[x][y]=1;
				}
					x=a[j][0]-2;y=a[j][1]+1;
					if (x==x1&&y==y1) 
				{
					bo=0;
					break;
				}
            	else if ((!c[x][y]&&x>=0&&x<l&&y>=0&&y<l)&&(x>x0-4||x>x1-4)&&(x<x0+4||x<x1+4)&&(y>y0-4||y>y1-4)&&(y<y0+4||y<y1+4)) 
				{   
					i++;
					a[i][0]=x;
					a[i][1]=y;c[x][y]=1;
				}
					x=a[j][0]-2;y=a[j][1]-1;
					if (x==x1&&y==y1) 
				{
					bo=0;
					break;
				}
            	else if ((!c[x][y]&&x>=0&&x<l&&y>=0&&y<l)&&(x>x0-4||x>x1-4)&&(x<x0+4||x<x1+4)&&(y>y0-4||y>y1-4)&&(y<y0+4||y<y1+4))
				{   
					i++;
					a[i][0]=x;
					a[i][1]=y;c[x][y]=1;
				}
					x=a[j][0]-1;y=a[j][1]+2;
					if (x==x1&&y==y1) 
				{
					bo=0;
					break;
				}
            	else if ((!c[x][y]&&x>=0&&x<l&&y>=0&&y<l)&&(x>x0-4||x>x1-4)&&(x<x0+4||x<x1+4)&&(y>y0-4||y>y1-4)&&(y<y0+4||y<y1+4))
				{   
					i++;
					a[i][0]=x;
					a[i][1]=y;c[x][y]=1;
				}
					x=a[j][0]-1;y=a[j][1]-2;
					if (x==x1&&y==y1) 
				{
					bo=0;
					break;
				}
            	else if ((!c[x][y]&&x>=0&&x<l&&y>=0&&y<l)&&(x>x0-4||x>x1-4)&&(x<x0+4||x<x1+4)&&(y>y0-4||y>y1-4)&&(y<y0+4||y<y1+4))
				{   
					i++;
					a[i][0]=x;
					a[i][1]=y;c[x][y]=1;
				}
			}
		}
		printf("%d\n",k);
	}
  }
	return 0;
}


2、我参考题解,给出了优化,把8个“if“语句用一个循环代替,然后优化了初始化步骤。

#include<stdio.h>
int main()
{
	short l,n,x,y,x1,y1,k=0,x0,y0,x2,y2;
	int i,j,d,e,ii;
	short c[300][300],a[90000][2];
	short bo;
	short dx[8]={1,1,2,2,-1,-1,-2,-2},dy[8]={2,-2,1,-1,2,-2,1,-1};
	scanf("%d",&n);
  while (n--)
  {
	  k=0;
	scanf("%d",&l);
	scanf("%d%d%d%d",&x,&y,&x1,&y1);
	if ((x==x1)&&(y==y1)) printf("%d\n",k);
	else
	{	
		x0=x;y0=y;
		a[0][0]=x;a[0][1]=y;
		if (x0<=x1) x2=x1;
		else {x2=x0;x0=x1;}
		if (y0<=y1) y2=y1;
		else {y2=y0;y0=y1;}
		if (x0-2>=0) x0=x0-2;else x0=0;
		if (y0-2>=0) y0=y0-2;else y0=0;
		if (x2+2<=l) x2=x2+2;else x2=l-1;
		if (y2+2<=l) y2=y2+2;else y2=l-1;
		for (i=x0;i<=x2;i++)
			for (j=y0;j<=y2;j++)
				c[i][j]=0;
			i=0;d=0;e=-1;bo=1;
		while (bo)
		{
			k++;
			d=e+1;e=i;
			for (j=d;j<=e;j++)
			{
			  for (ii=0;ii<8;ii++)
			  {
				  x=a[j][0]+dx[ii];
				  y=a[j][1]+dy[ii];
				  	if (x==x1&&y==y1) 
				{
					bo=0;
					j=e+1;
					break;
				}
				else if (!c[x][y]&&x>=x0&&x<=x2&&y>=y0&&y<=y2)
				{   
					i++;
					a[i][0]=x;
					a[i][1]=y;
					c[x][y]=1;
				}
			  }
			}
		}
		printf("%d\n",k);
	}
  }
	return 0;
}


3、运用队列的bfs

#include <iostream>  
#include <queue>  
using namespace std;   
   int xf,yf,xl,yl,n,dis[300][300],map[300][300];  
   int dx[8]={1,1,-1,-1,2,2,-2,-2};  
   int dy[8]={2,-2,2,-2,1,-1,1,-1};  
void bfs()
{  
   int vx,vy,tx,ty,i,bo=1;  
   queue <int>q;   
   memset(map,0,sizeof(map));
   memset(dis,0,sizeof(dis));  
    dis[xf][yf]=1;  
       q.push(xf);  
       q.push(yf);  
     while((!q.empty())&&bo)
	{   
           vx=q.front();q.pop();  
           vy=q.front();q.pop();
              for(i=0;i<8;i++)
	       {  
                  tx=vx+dx[i];  
                  ty=vy+dy[i];  
		     if(tx==xl && ty==yl) 
			 {
		            bo=0;
		            map[tx][ty]=map[vx][vy]+1;
			    break;
			  }
	             else if(!dis[tx][ty] && tx<n && tx>=0 && ty>=0 && ty<n)
			  {  
                            q.push(tx);  
                            q.push(ty);  
                            dis[tx][ty]=1;
			    map[tx][ty]=map[vx][vy]+1;  
                          }  
              } 
        }  
}  
int main()
{  
   int t;  
   scanf("%d",&t);  
   while(t--)
   {  
      scanf("%d",&n);  
      scanf("%d%d%d%d",&xf,&yf,&xl,&yl); 
	  map[xl][yl]=0;
		if(xf==xl && yf==yl) printf("%d\n",map[xl][yl]); 
		else
		{
		   bfs();  
                   printf("%d\n",map[xl][yl]); 
		} 
   }  
  return 0;  
}  



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值