【floyd+枚举】poj1178

Camelot

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
  
题目大意:在一个8*8的棋盘上有一个国王和若干个骑士,问国王和骑士全部走到一个格子里最少的总步数是多少
国王和骑士的每一步的走法分别如上图2和3所示,并且如果国王遇到一个骑士,骑士就可以载上国王一起走(注意并不是多个骑士啊,即如果国王和多个骑士走到一格也只有一个骑士上国王)
  
思路:
先求出国王和骑士分别从一个点到另一个点的最少步数(我用的floyd,也可以用广搜)
然后枚举终点,哪一个骑士去接国王,国王和骑士相遇点,看哪种组合总步数最少(64*64*64)
  
24号晚上在寝室做这个题真是出各种错,有几天没做题手残就加重了,连什么i,j打反了都出现了于是那天将近折腾了将近一个晚上一直到熄灯都还WA着呢……(于是我会说我在梦中跳了几天的棋盘格子吗?o(╯□╰)o)
今天读一遍发现果然脑残啊啊啊,在处理那个国王一步就能到达的点的时候左右两个方向写掉了……果然那个一步就能走的方向一个一个判断是个极度不科学的事情,还是应该弄成一个常量数组用循环的(这样的话记得给图加上边框!)
代码改来改去简直都要不能忍了!!
   
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define INF 2147483647;

long n, king;
long knights[100];

long f[100][100];
long g[100][100];

inline long min(long a, long b)
{
    return a > b ? b : a;
}

void prepare()
{
    memset(f, 127, sizeof(f));

    for (long i = 1; i <= 8; i++)
    for (long j = 1; j <= 8; j++)
    {
        long t1 = (i - 1) * 8 + j;
        if (i >= 3)
        {
            if (j >= 2)
            {
                long t2 = (i - 3) * 8 + j - 1;
                f[t1][t2] = f[t2][t1] = 1;
            }
            if (j <= 7)
            {
                long t2 = (i - 3) * 8 + j + 1;
                f[t1][t2] = f[t2][t1] = 1;
            }
        }

        if (i >= 2)
        {
            if (j >= 3)
            {
                long t2 = (i - 2) * 8 + j - 2;
                f[t1][t2] = f[t2][t1] = 1;
            }
            if (j <= 6)
            {
                long t2 = (i - 2) * 8 + j + 2;
                f[t1][t2] = f[t2][t1] = 1;
            }

        }

        if (i <= 8)
        {
            if (j >= 3)
            {
                long t2 = i * 8 + j - 2;
                f[t1][t2] = f[t2][t1] = 1;
            }
            if (j <= 6)
            {
                long t2 = i * 8 + j + 2;
                f[t1][t2] = f[t2][t1] = 1;
            }

        }

        if (i <= 7)
        {
            if (j >= 2)
            {
                long t2 = (i + 1) * 8 + j - 1;
                f[t1][t2] = f[t2][t1] = 1;
            }
            if (j <= 7)
            {
                long t2 = (i + 1) * 8 + j + 1;
                f[t1][t2] = f[t2][t1] = 1;
            }
        }

    }


    memset(g, 127, sizeof(g));
    for (long i = 1; i <= 8; i++)
    for (long j = 1; j <= 8; j++)
    {
        long t1 = (i - 1) * 8 + j;
        if (i >= 2)
        {
            long t2 = (i - 2) * 8 + j;
            g[t1][t2] = g[t2][t1] = 1;
            if (j >= 2)
            {
                long t2 = (i - 2) * 8 + j - 1;
                g[t1][t2] = g[t2][t1] = 1;
            }
            if (j <= 7)
            {
                long t2 = (i - 2) * 8 + j + 1;
                g[t1][t2] = g[t2][t1] = 1;
            }
        }

        if (i <= 7)
        {
            long t2 = i * 8 + j;
            g[t1][t2] = g[t2][t1] = 1;
            if (j >= 2)
            {
                long t2 = i * 8 + j - 1;
                g[t1][t2] = g[t2][t1] = 1;
            }
            if (j <= 7)
            {
                long t2 = i * 8 + j + 1;
                g[t1][t2] = g[t2][t1] = 1;
            }
        }
        if (j >= 2)
        {
            long t2 = (i - 1) * 8 + j - 1;
            g[t1][t2] = g[t2][t1] = 1;
        }
        if (j <= 7)
        {
            long t2 = (i - 1) * 8 + j + 1;
            g[t1][t2] = g[t2][t1] = 1;
        }

    }


}
void floyd1()
{
    for (long i = 1; i <= 64; i++)
        f[i][i] = 0;
    for (long k = 1; k <= 64; k++)
        for (long i = 1; i <= 64; i++)
            for (long j = 1; j <= 64; j++)
            {
                if ((i != j) && (j != k) && (k != i))
                {
                    if ((f[i][k] < 10000)&& (f[k][j] < 10000))
                        f[i][j] = min(f[i][j], f[i][k] + f[k][j]);
                }
            }

}

void floyd2()
{
    for (long i = 1; i <= 64; i++)
        g[i][i] = 0;
    for (long k = 1; k <= 64; k++)
        for (long i = 1; i <= 64; i++)
            for (long j = 1; j <= 64; j++)
            {
                if ((i != j) && (j != k) && (k != i))
                {
                    if ((g[i][k] < 10000)&& (g[k][j] < 10000))
                        g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
                }

            }

}

long solve(long x,long y)
///最后在x点汇合且有一个骑士在y点遇上国王(实际上包含了国王自己走到汇合点的方案)
{
    long ret = INF;
    for (long i = 1; i <= n; i++)  ///枚举接国王的骑士是哪一个
    {
        long sum = 0 ;
        sum += f[knights[i]][y] + g[king][y] + f[y][x];
        for (long j = 1; j <= n; j++)
        {
            if (i != j)
                sum += f[knights[j]][x];
        }
        ret = min(ret, sum);
    }
    return ret;
}
int main()
{
    char c[200];
    scanf("%s", c);

    long x = (c[0] - 'A') + 1;
    long y = (c[1] - '0');
    king = (x  - 1) * 8 + y;
    long k = 1;
    for (long i = 2; i < strlen(c); i += 2)
    {
        x = (c[i] - 'A') + 1;
        y = (c[i + 1] - '0');
        knights[k] =  (x  - 1) * 8 + y;
        k++;
    }

    n = k - 1;
    prepare();
    floyd1();
    floyd2();
    long re = INF;
    for (long i = 1; i <= 64; i++)
    {
        long t = INF;
        for (long j = 1; j <= 64; j++)
        {
            t = min(t, solve(i, j));
        }
        if (t < re) re = t;
    }
    printf("%d\n", re);

    return 0;
}


  
  
全部评论

相关推荐

不愿透露姓名的神秘牛友
2025-12-17 16:48
今天九点半到公司,我跟往常一样先扫了眼电脑,屁活儿没有。寻思着没事干,就去蹲了个厕所,回来摸出手机刷了会儿。结果老板刚好路过,拍了我一下说上班别玩手机,我吓得赶紧揣兜里。也就过了四十分钟吧,我的直属领导把我叫到小隔间,上来就给我一句:“你玩手机这事儿把老板惹毛了,说白了,你可以重新找工作了,等下&nbsp;HR&nbsp;会来跟你谈。”&nbsp;我当时脑子直接宕机,一句话都没憋出来。后面&nbsp;HR&nbsp;找我谈话,直属领导也在旁边。HR&nbsp;说我这毛病不是一次两次了,属于屡教不改,不光上班玩手机,还用公司电脑看论文、弄学校的事儿。我当时人都傻了,上班摸鱼是不对,可我都是闲得发慌的时候才摸啊!而且玩手机这事儿,从来没人跟我说过后果这么严重,更没人告诉我在公司学个习也算犯错!连一次口头提醒都没有,哪儿来的屡教不改啊?更让我膈应的是,昨天部门刚开了会,说四个实习生里留一个转正,让大家好好表现。结果今天我就因为玩手机被开了。但搞笑的是,开会前直属领导就把我叫去小会议室,明明白白告诉我:“转正这事儿你就别想了,你的学历达不到我们部门要求,当初招你进来也没打算给你这个机会。”合着我没入贵厂的眼是吧?可我都已经被排除在转正名单外了,摸个鱼至于直接把我开了吗?真的太离谱了!
rush$0522:转正名单没进,大概率本来就没打算留你
摸鱼被leader发现了...
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务