poj1178 Camelot(floyd+枚舉)

Camelot
Time Limit: 1000MS   Memory Limit: 10000K
Total 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;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章