COCI ‘20 Contest 1 #1 Patkice

本文介绍了一道编程竞赛题目,涉及到字符矩阵处理和路径寻找算法。题目中,橡皮鸭借助洋流在地图上移动,目标是找到最短路径到达标记为'x'的岛屿。解决方案包括遍历地图,模拟不同方向的航行,计算最短路径。通过这个算法,可以判断鸭子能否到达目标岛屿以及所需最短时间。

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

题目描述

       不久前,在一个遥远的热带土地上,生活着三只橡皮鸭。 在一个炎热的夏日,鸭子躺在沙滩上时,他们决定前往附近的一个小岛。 由于鸭子喜欢冒险,所以他们决定利用洋流在旧的黑色雨伞中旅行。
       由于鸭子是经验丰富的海洋探险者,因此在航行之前,它们标记出洋流地图。 在地图上,鸭子所居住的岛上标有字母“o”。 鸭子可以从四个方向中的任意一个开始航行:北–N,东–E,西–W和南–S。
       这些海洋中的洋流沿四个方向之一移动,并按以下方式在地图上标记:东向西’<’,西向东’>’,北向南’v’和南向北’^ '。 当鸭子在有洋流的单元格上时,它们会沿洋流方向移动一个单元格。 这些海洋中的洋流很特别,因为它们永远不会引向地图之外,并且它们不会形成涡流(如果鸭子跟随洋流,它们会绕圈运动)。
       平静的海面以点号“.”标记。 如果洋流将鸭子带到平静无洋流的单元格中或返回起始岛屿,它们将无法继续航行。 鸭子想参观的小岛上标有字母“x”。
       鸭子们不想停止他们的沙滩派对。 他们恳请您告诉他们是否有可能到达另一个岛屿,如果可以,他们应该朝哪个方向航行。 由于其中一只鸭子晕船,它们会要求您选择使航程尽可能短的方向。 如果存在多个产生相同最小行驶时间的方向,则应选择按字母顺序排列的第一个方向。

输入

第一行包含整数 r 和 s (3≤r,s≤100),即地图的行数和列数。接下来r 行每行包含 s个字符o<>v^.x,代表洋流图。在地图上总是只有一个字符o,只有一个字符x。字符o永远不会位于第一行或最后一行或列中。

输出

如果鸭子无法到达另一个岛屿,请打印:(。
否则,请在第一行中打印:)。在第二行中,打印开始方向(N,E,W 或S)。

说明

在30分的测试用例中,有效的开始方向(如果存在)将是唯一的。

样例输入1

6 6
..>>>v
.o^..v
.v.<.v
.>>^.v
.x<<<<
......

样例输出1

:)
E

样例输出1的说明

在第一个示例中,如果鸭子向东以外的任何方向开始航行,它们将最终到达平静的海面中而不会到达另一个岛屿。

样例输入2

5 5
v<<<<
\>v.>^
v<.o.
\>>v>v
..>>x

样例输出2

:)
S

样例输出2的说明

在第二个示例中,如果鸭子先向北或向南走,它们将到达另一个岛。他们选择南向,因为它更短。

样例输入3

3 3
x>.
.o^
^<.

样例输出3

:(

解释

markdown中 :)表示emoji表情,故用空格隔开,实际无空格

solution

我们将输入数据存在mat[ ][ ]二维数组中。 起始坐标(ox,oy),因此math [ox] [oy] =‘o’。
我们将尝试将鸭子移动到四个方向中的每个方向,产生四个路径。 对于这些路径中的每一个,我们都会计算到达“ x”之前它经过了多少个单元格,如果路径以“.”或“ o”结尾,则距离是无限的。
实现:我们从(ox + 1,oy),(ox-1,oy),(ox,oy + 1)和(ox,oy-1)开始运行以下算法四次。
鸭子当前位置为(px,py),并将变量d中的路径长度初始化为0。如果mat [px] [py]的字符为’<> ^ v’其中之一,则增加d并移动(px ,py)指向相应的方向。 (我们可以使用dict或std :: map,将描述方向的有序对映射到字符,例如{’>’:( 0,1)})。
如果mat [px] [py]等于“ o”或“.”,则设置d =∞并停止处理此路径。
如果mat [px] [py]等于“ x”,我们就完成了。
在上一部分之后,我们有距离dN,dE,dW,dS。 如果所有di =∞,则没有解,我们打印:(。
否则,我们打印:)和di最小的相应字母i,若存在多个相等的最小值,按字母序最小输出。

#include <cstdio>
#include <algorithm>

using namespace std;

const int MAXN = 102;
const int INF = MAXN*MAXN;

typedef pair<int, int> ii;

ii operator+(const ii& a, const ii& b){
    return ii(a.first + b.first, a.second + b.second);
}


int r,s;
char mat[MAXN][MAXN];


//ENSW
ii delta[] = {ii(0, 1), ii(-1, 0), ii(1, 0), ii(0, -1)};


int measure(ii p){
    int d = 0;
    for(;;){
        switch(mat[p.first][p.second]){
        case 'x':
            return d;
        case '>':
            p = p+delta[0];
            break;
        case '^':
            p = p+delta[1];
            break;
        case 'v':
            p = p+delta[2];
            break;
        case '<':
            p = p+delta[3];
            break;
        default:
            return INF;
        }
        d++;
    }
    return INF;
}

int main(){
    scanf("%d%d", &r, &s);
    for(int i=0;i<r;i++){
        scanf("%s", mat[i]);
    }
    ii start;
    for(int i=0;i<r;i++){
        for(int j=0;j<s;j++){
            if(mat[i][j] == 'o')
                start = ii(i, j);
        }
    }
    int bl = INF;
    char s = 0;
    for(int i=0;i<4;i++){
        int len = measure(start + delta[i]);
        if(len<bl){
            bl = len;
            s = "ENSW"[i];
        }
    }
    if(s)
        printf(":)\n%c\n", s);
    else
        puts(":(");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值