小X与机器人 (betago) 题解

题目描述

小 X 最近对战胜韩国围棋大神李世石的 AlphaGo 很感兴趣,所以小 X 自己写了一个叫 做 BetaGo的人工智能程序(简称 AI) , 这个 BetaGo 会做什么呢?
小 X 首先想要让 BetaGo 做到自己在棋盘上落子, 这一点 AlphaGo 是由程序员来完成的。小 X 的设想是这样的: 在棋盘的边框上放置一个小机器人, 这个小机器人会沿着棋盘的边框移动到最接近落子点的位置,然后伸出它的机械臂将棋子放到棋盘上。 这里面最关键的一步是如何让小机器人在棋盘的边框上沿着最短的路径移动,小 X 想请你帮他编个程序解决这个问题。
众所周知,围棋棋盘大小为 19 ×  19(如下图所示) , 图中加粗的一圈即为边框。
小X与机器人 (betago) 题解
我们用一对整数 (x, y) 来表示棋盘上第 x 条横线(从下往上数)与第 y 条竖线(从左往右数)的交叉点,如上图中边框上的 A 点用( 6, 1) 表示, B 点用 (10, 19) 表示,小机器人初始时放置在 (x1,y1) 这个位置上, 它想要移动到 (x2, y2) 这个位置上。 (x1, y1) 和(x2, y2) 一定是棋盘边框上的交叉点每一步小机器人可以从当前位置移动到相邻(上下左右)的某个位置上, 即每次可以从 (x, y) 移动到 (x - 1, y) 、 (x + 1, y) 、 (x, y - 1) 、 (x, y + 1) 四个位置中的一个, 但是它不能走出或走进棋盘,也就是说它只能沿着棋盘的边框移动到相邻位置, 这就意味着任一时刻相邻位置都恰好只有两个。
BetaGo 会告诉小机器人最少需要走多少步, 但小 X 还是很担心 BetaGo 有的时候会失控,从而告诉他一个错误值。
为此小 X 只好求助你, 希望你编一个程序计算从 (x1, y1) 沿着棋盘的边框移动到 (x2, y2) 最少需 要 走 多 少步 。 上 图 中 从 A 点 ( 6 , 1 ) 移 动 到 B 点 (10 , 19) 最 少需 要 走 32 步 , 移 动 路线 是 :( 6 , 1 ) → ( 5 , 1 ) → ( 4 , 1 ) → ( 3 , 1 ) → ( 2 , 1 ) → ( 1 , 1 ) → (1 , 2 ) → (1 , 3 ) →……→(1, 19) →(2, 19) →……→(10, 19)

输入

输入数据仅有一行包含四个用空格隔开的正整数表示 x1, y1, x2, y2。
数据保证 (x1, y1) , (x2, y2) 一定是棋盘边框上的交叉点。

输出

输出一行包含一个整数 ans, 表示小机器人从 (x1, y1) 移动到 (x2, y2) 的最少步数。

样例输入 

6 1 10 19

样例输出 

32

【数据范围】

对于 30%的数据, (x1, y1) , (x2, y2) 在同一条边框上
对于另外 30%的数据, (x1, y1) , (x2, y2) 在相邻的两条边框上
对于另外 40%的数据, (x1, y1) , (x2, y2) 在相对的两条边框上
时间限制:1s
空间限制:256M
 

题解

方法一:分类讨论

三种情况:

(1)对面两个点,要分两路比较

(2)相邻直线上的两个点(x横坐标y纵坐标)abs(x1-x2)+abs(y1-y2)

(3)同一条线上abs(x1-x2)或abs(y1-y2)

参考代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
int solve(int x,int y){
    if(x-y>=0) return x-y;
    return y-x;
}
signed main()
{
    //freopen(".in","r",stdin);
    //freopen(".out","w",stdout);
    int x1,y1,x2,y2,a,b;
    scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2);
    if(abs(x1-x2)==18){
        a=18+y1-1+y2-1;
        b=18+19-y1+19-y2; 
    }
    else if(abs(y1-y2)==18){
        a=18+x1-1+x2-1;
        b=18+19-x1+19-x2; 
    }
    else if(x1==x2) a=solve(y1,y2);
    else if(y1==y2) a=solve(x1,x2);
    else a=solve(x1,x2)+solve(y1,y2);
    if((a>b)&&(b!=0)) printf("%lld\n",b);
    else printf("%lld\n",a);
    return 0;
}

方法二:广度优先搜索(BFS)

参考代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
queue<int>x,y,sum;
int vis[20][20],sx,sy,tx,ty,xx,yy,summ;
signed main()
{
    //freopen(".in","r",stdin);
    //freopen(".out","w",stdout);
    scanf("%lld%lld%lld%lld",&sx,&sy,&tx,&ty);
    if(sx==tx&&sy==ty){
        printf("0\n");
        return 0;
    }
    x.push(sx),y.push(sy),sum.push(0);
    while(!x.empty()){
        xx=x.front(),yy=y.front(),summ=sum.front();
        vis[xx][yy]=summ;
        if(xx==1||xx==19){
            if(yy<19&&vis[xx][yy+1]==0)
                x.push(xx),y.push(yy+1),sum.push(summ+1);
            if(yy>1&&vis[xx][yy-1]==0)
                x.push(xx),y.push(yy-1),sum.push(summ+1);
        }
        if(yy==1||yy==19){
            if(xx<19&&vis[xx+1][yy]==0)
                x.push(xx+1),y.push(yy),sum.push(summ+1);
            if(xx>1&&vis[xx-1][yy]==0)
                x.push(xx-1),y.push(yy),sum.push(summ+1);
        }
        if(xx==sx&&yy==sy) vis[xx][yy]=1;
        x.pop(),y.pop(),sum.pop();
    }
    printf("%lld\n",vis[tx][ty]);
    return 0;
}

相关推荐