poj1178 Camelot(floyd+枚举)

来源:互联网 发布:查韩服lol战绩软件 编辑:程序博客网 时间:2024/06/11 16:59
Camelot
Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 2558 Accepted: 1190

Description

Centuries ago, King Arthur and the Knights of the Round Table used to meet every year on New Year's Day to celebrate their fellowship. In remembrance of these events, we consider a board game for one player, on which one king and several knight pieces are placed at random on distinct squares.
The Board is an 8x8 array of squares. The King can move to any adjacent square, as shown in Figure 2, as long as it does not fall off the board. A Knight can jump as shown in Figure 3, as long as it does not fall off the board.

During the play, the player can place more than one piece in the same square. The board squares are assumed big enough so that a piece is never an obstacle for other piece to move freely.
The player's goal is to move the pieces so as to gather them all in the same square, in the smallest possible number of moves. To achieve this, he must move the pieces as prescribed above. Additionally, whenever the king and one or more knights are placed in the same square, the player may choose to move the king and one of the knights together henceforth, as a single knight, up to the final gathering point. Moving the knight together with the king counts as a single move.

Write a program to compute the minimum number of moves the player must perform to produce the gathering.

Input

Your program is to read from standard input. The input contains the initial board configuration, encoded as a character string. The string contains a sequence of up to 64 distinct board positions, being the first one the position of the king and the remaining ones those of the knights. Each position is a letter-digit pair. The letter indicates the horizontal board coordinate, the digit indicates the vertical board coordinate.

0 <= number of knights <= 63

Output

Your program is to write to standard output. The output must contain a single line with an integer indicating the minimum number of moves the player must perform to produce the gathering.

Sample Input

D4A3A8H1H8

Sample Output

10题目大意:在棋盘上,给定一个国王的位置,与多个骑士的位置,给定国王的方向,和骑士的方向。当国王与骑士相遇后,骑士会带着国王走,即国王就变成了该骑士。问所有的人(国王和所有骑士)相遇在一点时的最短路程。输入:D4A3A8H1H8,其中D4表示国王的位置,后面的每两对表示的是其他骑士的位置。思路:无论怎么走,存在最短路程那个解答方案总是存在的。而且我们也很容易知道所有方案的解答集合,即国王与每个骑士中的一位在64点中的一个点相遇,并且,所有的人在64点中的一个点集结。这就是整个解答方案集合,在这个集合中,总会存在一个最小路程。因此,我们很容易想到枚举法,枚举国王与每个骑士中的一位在64点中的一个点相遇,再枚举所有人在64点中的一点集合。思路有了,可是怎么处理移动的距离问呢?答案是floyd,通过floyd遇处理,可以得到国王和骑士在棋盘上整个移动到其他点的最短路径。故在之后枚举的过程中就相当轻松了。总的复杂度为0(64^3)注意一下:我的代码过程中,将图示的象棋棋盘坐标,转变成我们习惯的二维数组那种坐标方向。/*
/*    @author : liuwen*/#include <iostream>#include <algorithm>#include <cstring>#include <cstdio>#include <cstdlib>#include <queue>#include <stack>#include <map>#include <vector>#include <cmath>using namespace std;const int dirKing[8][2]={{-1,-1},{-1,0},{-1,1},{0,-1},{0,1},{1,-1},{1,0},{1,1}};//国王方向const int dirKnight[8][2]={{-1,-2},{-2,-1},{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2}};//骑士方向const int inf=0x1fffffff;int kingdist[65][65],knightdist[65][65];void move1(){    for(int i=0;i<64;i++)        for(int j=0;j<64;j++)            kingdist[i][j]=(i==j)?0:inf;    for(int i=0;i<64;i++){        int x=i/8;        int y=i%8;        for(int k=0;k<8;k++){            int nowX=x+dirKing[k][0];            int nowY=y+dirKing[k][1];            if(nowX>=0&&nowX<8&&nowY>=0&&nowY<8){                kingdist[i][nowX*8+nowY]=1;            }        }    }}void move2(){    for(int i=0;i<64;i++)        for(int j=0;j<64;j++)            knightdist[i][j]=(i==j)?0:inf;    for(int i=0;i<64;i++){        int x=i/8;        int y=i%8;        for(int k=0;k<8;k++){            int nowX=x+dirKnight[k][0];            int nowY=y+dirKnight[k][1];            if(nowX>=0&&nowX<8&&nowY>=0&&nowY<8){                knightdist[i][nowX*8+nowY]=1;            }        }    }}void floyd(int dist[65][65]){    for(int k=0;k<64;k++)        for(int i=0;i<64;i++)            for(int j=0;j<64;j++)                dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j]);}int main(){    //freopen("in.txt","r",stdin);    move1();    move2();    floyd(kingdist);    floyd(knightdist);    char str[130];    int cnt,kingPos,knightPos[64];    while(scanf("%s",str)!=EOF){        kingPos=('8'-str[1])*8+str[0]-'A';  //我的坐标转变了,与题目图示不同        cnt=0;        for(int i=2;i<strlen(str);i+=2){            knightPos[cnt++]=('8'-str[i+1])*8+str[i]-'A';//我的坐标转变了,与题目图示不同        }        int minStep=inf;        for(int i=0;i<cnt;i++){ //枚举国王与每个骑士相遇            for(int x=0;x<64;x++){ //枚举国王与骑士相遇在x点                int tmp1=kingdist[kingPos][x]+knightdist[knightPos[i]][x];//国王与骑士相遇在x点所走的路程                for(int y=0;y<64;y++){ //所有的人(国王和骑士)都集结在y点                    int tmp2=0;                    for(int k=0;k<cnt;k++){                        if(k!=i)   tmp2+=knightdist[knightPos[k]][y];//所有骑士走到y点一共的路程                    }                    minStep=min(minStep,tmp1+tmp2+knightdist[x][y]);//国王与骑士在x点相遇后,骑士带着国王一起走向y点,故是tmp1+tmp2+knightdist[x][y]                }            }        }        printf("%d\n",minStep);    }    return 0;}



0 0