POJ1178枚举三个地方(所有点都去同一个点)

博客探讨了如何通过枚举终点来解决POJ1178问题,强调了在确定三个关键点后计算距离的重要性。文中提到可以使用广搜或最短路预处理方法,并指出国王的最短路径计算为两点间绝对坐标差的最大值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:
      有一个国王和很多骑士,他们都要到某一个点去集合,然后问所有人都到达某个终点的距离和最小是多少?过程中如果国王遇到了一个骑士的话,国王就可以和骑士一起按照骑士的走法走,这是两个人算一个人,同时国王有八种走法,骑士也有八种走法,两个不一样。


思路:

      可以枚举终点,和骑士相交的点还有和那个骑士相交,只要确定这三个点后距离就出来了,求距离可以用广搜预处理,也可以用最短路预处理,不管用什么记得细心点,还有对于国王的最短路直接可以算出来,就是max(abs(x1-x2),abs(y1-y2))。


#include<queue>
#include<stdio.h>
#include<string.h>

#define N 70
#define INF 1000000000

using namespace std;

typedef struct
{
    int x ,y ,t;
}NODE;

NODE xin ,tou;
NODE node[N];
int dis[N][N];
int mark[N];
int dir[8][2] = {1 ,2 ,1 ,-2 ,-1 ,2 ,-1 ,-2 ,2 ,1 ,2 ,-1 ,-2 ,1 ,-2 ,-1};


int minn(int x ,int y)
{
    return x < y ? x : y;
}

int maxx(int x ,int y)
{
    return x > y ? x : y;
}

int abss(int x)
{
    return x > 0 ? x : -x;
}

bool ok(int x ,int y)
{
    return x >= 1 && x <= 8 && y >= 1 && y <= 8 && !mark[(x-1)*8+y];
}

void BFS(int x ,int y)
{
    queue<NODE>q;
    xin.x = x ,xin.y = y ,xin.t = 0;
    memset(mark ,0 ,sizeof(mark));
    mark[(x-1)*8+y] = 1;
    dis[(x-1)*8+y][(x-1)*8+y] = 0;
    q.push(xin);

    while(!q.empty())
    {
        tou = q.front();
        dis[(x-1)*8+y][(tou.x-1)*8+tou.y] = tou.t;
        q.pop();
        for(int i = 0 ;i < 8 ;i ++)
        {
            xin.x = tou.x + dir[i][0];
            xin.y = tou.y + dir[i][1];
            xin.t = tou.t + 1;
            if(ok(xin.x ,xin.y))
            {
                mark[(xin.x-1)*8+xin.y] = 1;
                q.push(xin);
            }
        }
    }
    return ;
}


int main ()
{
    char str[150];
    int i ,j ,k ,x ,y;
    for(i = 1 ;i <= 8 ;i ++)
    for(j = 1 ;j <= 8 ;j ++)
    BFS(i ,j);
    while(~scanf("%s" ,str))
    {
        int len = strlen(str);
        int id = 0;
        for(i = 0 ;i < len ;i += 2)
        {
            x = str[i+1] - '0';
            y = str[i] - 'A' + 1;
            node[++id].x = x;
            node[id].y = y;
        }
        int ans = INF;
        for(i = 1 ;i <= 64 ;i ++) //终点
        for(j = 1 ;j <= 64 ;j ++) //相遇点
        for(k = 2 ;k <= id ;k ++) //相遇的那个骑士
        {
            int s = 0;
            x = (j-1) / 8 + 1;
            y = j % 8;
            if(!y) y = 8;
            s = maxx(abss(x - node[1].x),abss(y - node[1].y));
            s += dis[(node[k].x - 1) * 8 + node[k].y][j];
            s += dis[j][i];
            for(int w = 2 ;w <= id ;w ++)
            {
               if(w == k) continue;
               s += dis[(node[w].x-1)*8+node[w].y][i];
            }
            if(s < ans) ans = s;
        }
        if(id == 1) ans = 0;
        printf("%d\n" ,ans);
    }
    return 0;

}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值