ACM 广搜优先 Knight Moves

来源:互联网 发布:js post 下载文件 编辑:程序博客网 时间:2024/06/05 05:03

寒假训练二里面的A题,搜了一下发现题库居然还有一题名字一样的。

正好方法也差不多,所以顺便就一起写了。(广搜优先)


TOJ 1133: Knight Moves

描述

A friend of you is doing research on the Traveling Knight Problem (TKP) where you are to find the shortest closed tour of knight moves that visits each square of a given set of n squares on a chessboard exactly once. He thinks that the most difficult part of the problem is determining the smallest number of knight moves between two given squares and that, once you have accomplished this, finding the tour would be easy.
Of course you know that it is vice versa. So you offer him to write a program that solves the "difficult" part.

Your job is to write a program that takes two squares a and b as input and then determines the number of knight moves on a shortest route from a to b.

输入

The input will contain one or more test cases. Each test case consists of one line containing two squares separated by one space. A square is a string consisting of a letter (a-h) representing the column and a digit (1-8) representing the row on the chessboard.

输出

For each test case, print one line saying "To get from xx to yy takes n knight moves.".

样例输入

样例输出


题目意思:有一颗棋子A走到B需要几步。以下用的是广搜,还有用栈的地方我详细解说了。

#include <iostream>#include <cstdio>#include <cstring>#include <queue>using namespace std;int c[9][9];int dir[8][2] = {{-2,-1},{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2},{-1,-2}};//8种走法 typedef struct{    int x,y,count;}node;node start,finish;int bfs(){    memset(c,0,sizeof(c));//作用等同于int c[9][9]={0};    node pre,cur;    start.count=0;    queue<node> q;//创建队列q     q.push(start);//push(x) 将x压入队列的末端    c[start.x][start.y]=1;//起点走过了     while(!q.empty())//队列非空     {        pre=q.front();//返回第一个元素(队顶元素)        q.pop();//弹出队列的第一个元素(队顶元素)        if(pre.x==finish.x&&pre.y==finish.y)//走到终点了         return pre.count;        for(int i=0;i<8;i++)        {            cur.x=pre.x+dir[i][0];            cur.y=pre.y+dir[i][1];            if(cur.x<1||cur.x>8||cur.y<1||cur.y>8)continue;//出界了             if(c[cur.x][cur.y]==1)continue;//==1就是走过了 ,防止走回头路             c[cur.x][cur.y]=1;//标记走过了             cur.count=pre.count+1;//步数+1             q.push(cur);        }    }    return -1;}int main(){    char row,end;    int col,ed;    int min;    while(scanf("%c%d %c%d",&row,&col,&end,&ed)!=EOF)    {    getchar();         start.x = row-'a'+1;        start.y = col;        finish.x = end-'a'+1;        finish.y = ed;        if(start.x==finish.x&&start.y==finish.y)        min=0;        else  min=bfs();        printf("To get from %c%d to %c%d takes %d knight moves.\n",row,col,end,ed,min);    }    return 0;}


下面这题差不多,都是数字还简单点了...用的也是广搜优先。

然后在我百度的时候搜到一篇讲这个的,感觉很不错,因为他化简了。

还没拿到转载权..就贴个地址吧...

http://blog.csdn.net/nameofcsdn/article/details/52025142


TOJ  2481: Knight Moves

描述

Background
Mr Somurolov, fabulous chess-gamer indeed, asserts that no one else but him can move knights from one position to another so fast. Can you beat him?
The Problem
Your task is to write a program to calculate the minimum number of moves needed for a knight to reach one point from another, so that you have the chance to be faster than Somurolov.
For people not familiar with chess, the possible knight moves are shown in Figure 1.

输入

The input begins with the number n of scenarios on a single line by itself.
Next follow n scenarios. Each scenario consists of three lines containing integer numbers. The first line specifies the length l of a side of the chess board (4 <= l <= 300). The entire board has size l * l. The second and third line contain pair of integers {0, ..., l-1}*{0, ..., l-1} specifying the starting and ending position of the knight on the board. The integers are separated by a single blank. You can assume that the positions are valid positions on the chess board of that scenario.

输出

For each scenario of the input you have to calculate the minimal amount of knight moves which are necessary to move from the starting point to the ending point. If starting point and ending point are equal,distance is zero. The distance must be written on a single line.

样例输入

样例输出

题目意思:(数据代入说明)有3组数据,第一组数据,棋盘大小8*8,从(0,0)走到(7,0)需要5步。

这个是直接改的上面的代码。就是在判断出界的时候把>改成>=。

#include <iostream>#include <cstdio>#include <cstring>#include <queue>using namespace std;int c[301][301];//棋盘最大300 int m,dir[8][2]={{-2,-1},{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2},{-1,-2}};//8种走法 typedef struct{    int x,y,count;}node;node start,finish;int bfs(){    memset(c,0,sizeof(c));//作用等同于int c[301][301]={0};    node pre,cur;    start.count=0;    queue<node> q;//创建队列q     q.push(start);//push(x) 将x压入队列的末端    c[start.x][start.y]=1;//起点走过了     while(!q.empty())//队列非空     {        pre=q.front();//返回第一个元素(队顶元素)        q.pop();//弹出队列的第一个元素(队顶元素)        if(pre.x==finish.x&&pre.y==finish.y)//走到终点了         return pre.count;        for(int i=0;i<8;i++)        {            cur.x=pre.x+dir[i][0];            cur.y=pre.y+dir[i][1];            if(cur.x<0||cur.x>=m||cur.y<0||cur.y>=m)continue;//出界了  这里改了>=m             if(c[cur.x][cur.y]==1)continue;//==1就是走过了 ,防止走回头路             c[cur.x][cur.y]=1;//标记走过了             cur.count=pre.count+1;//步数+1             q.push(cur);        }    }    return -1;}int main(){    int min,n;    scanf("%d",&n);    while(n--)    { scanf("%d %d %d %d %d",&m,&start.x,&start.y,&finish.x,&finish.y);        if(start.x==finish.x&&start.y==finish.y)        min=0;        else  min=bfs();        printf("%d\n",min);    }    return 0;}

然后我在网上找了个简洁版...

#include<cstdio>#include<cstring>#include<queue>using namespace std;const int dir[8][2]={{-1,-2},{-2,-1},{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2}};struct node{int x,y,step;};bool used[301][301];int n;int startx,starty,endx,endy;node cur,pre;int bfs(){    int i,x,y;    queue<node>que;    cur.x=startx,cur.y=starty,cur.step=0;    memset(used,0,sizeof(used));    used[startx][starty]=1;    que.push(cur);    while(!que.empty())    {        cur=que.front(),que.pop();        if(cur.x==endx&&cur.y==endy)        return cur.step;        for(i=0;i<8;i++)        {            x=cur.x+dir[i][0];            y=cur.y+dir[i][1];            if(x>=0&&x<n&&y>=0&&y<n&&!used[x][y])            {                used[x][y]=1;                pre.x=x,pre.y=y,pre.step=cur.step+1;                que.push(pre);            }        }    }    return -1;}int main(){    int tCase;    scanf("%d",&tCase);    while(tCase--)    {        scanf("%d",&n);        scanf("%d%d%d%d",&startx,&starty,&endx,&endy);        printf("%d\n",bfs());    }    return 0;}



0 0