【转】POJ-2243-Knight Moves:DFS || BFS || Floyd 求最短路

DFS

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int knight[8][8];// 各点到起点的最短距离
int x[8]={-2, -1, 1, 2, -2, -1, 1, 2};
int y[8]={-1, -2, -2, -1, 1, 2, 2, 1};

void DFS(int i, int j, int dis)
{
        if(i<0||i>7||j<0||j>7||knight[i][j]<=dis)
            return;
        knight[i][j]=dis;
        for(int k=0; k<8; k++)
            DFS(i+x[k], j+y[k], dis+1);
}

int main()
{
        char S1[10], S2[10];
        while(cin>>S1>>S2)
        {
                memset(knight, 10, sizeof(knight));// 初始化距离较大 DFS时再更新

                DFS(S1[0]-'a', S1[1]-'1', 0);

                printf("To get from %s to %s takes %d knight moves.\n", S1, S2, knight[S2[0]-'a'][S2[1]-'1']);
        }
        return 0;
}

BFS

#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;

int x[8]={-2, -1, 1, 2, -2, -1, 1, 2};
int y[8]={-1, -2, -2, -1, 1, 2, 2, 1};

struct point
{
        int x, y;
        int  dis;
};

int main()
{
        queue<point>que;
        char S1[10], S2[10];
        while(cin>>S1>>S2)
        {
                while(!que.empty())
                    que.pop();
                point p;
                p.x=S1[0]-'a';
                p.y=S1[1]-'1';
                p.dis=0;
                que.push(p);
                while(!que.empty())
                {
                        p = que.front();
                        que.pop();
                        if(p.x==S2[0]-'a' && p.y==S2[1]-'1')
                            break;

                        point tmp;
                        for(int i=0; i<8; i++)
                        {
                                tmp.x=p.x+x[i];
                                tmp.y=p.y+y[i];
                                tmp.dis=p.dis+1;
                                if(tmp.x<0 || tmp.x>7 || tmp.y<0 || tmp.y>7)
                                        continue;
                                que.push(tmp);
                        }
                }
                printf("To get from %s to %s takes %d knight moves.\n", S1, S2, p.dis);
        }
        return 0;
}

Floyd

算法详解请点这里

应用于改题的思路:由于棋盘很小,而输入数据可能很大,则可以想到先打表存储每点到各点的最短路径,这样对于所有输入查表输出即可。

当然前提是从每一点出发可以到达任一点(题中有提到)

相对于DFS和BFS来说 Floyd的时间复杂度最小

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;

void Floyd(int k[][64])
{
        int dx, dy;// 两点间相对距离
        for(int i=0; i<64; k[i][i]=0,i++)
            for(int j=0; j<64; j++){

                dx=abs(i/8-j/8);
                dy=abs(i%8-j%8);

                if(dx==1&&dy==2 || dx==2&&dy==1)//      骑士一步的距离
                    k[i][j]=k[j][i]=1;
            }

        for(int l=0; l<64; l++)
            for(int i=0; i<64; i++)
                for(int j=0; j<64; j++){

                        if(k[i][l]+k[l][j]<k[i][j])
                            k[i][j]=k[i][l]+k[l][j];
                }
}

int main()
{
        char S1[10], S2[10];
        int knight[64][64];// 棋盘中每点到其余给点的距离 以骑士的步长为单位
        memset(knight, 10, sizeof(knight));//初始化为无穷
        Floyd(knight);// 打表 存储

        while(cin>>S1>>S2)
        {
                int x=(S1[0]-'a')*8+S1[1]-'1';
                int y=(S2[0]-'a')*8+S2[1]-'1';
                // 直接查表 打印结果
                printf("To get from %s to %s takes %d knight moves.\n", S1, S2, knight[x][y]);
        }
        return 0;
}

总结:Floyd算法适合稠密图 即图小数据量大 而BFS适合稀疏图 即图大数据量小。

posted @ 2015-08-14 19:09  _SunDaSheng  阅读(211)  评论(0编辑  收藏  举报