{ }codelper
값 타입과 참조 타입묶음 자료P0203

부딪히면 되돌아오는 로봇

H행 W열짜리 방 지도가 있다. 지도의 칸은 .(빈 칸), #(벽), S(로봇이 처음 있는 빈 칸) 가운데 하나이고, S는 정확히 하나다. 로봇은 U(위), D(아래), L(왼쪽), R(오른쪽)로 이루어진 명령 문자열을 앞에서부터 하나씩 따른다. 명령 하나마다 로봇은 그 방향으로 한 칸 움직인다. 움직인 칸이 지도 밖이거나 벽이면, 로봇은 움직이기 바로 전의 칸으로 되돌아오고 부딪힌 횟수가 1 늘어난다. 명령을 모두 따른 뒤 로봇이 있는 칸의 행 번호, 열 번호(둘 다 1부터 센다)와 부딪힌 횟수를 빈칸 하나씩 띄워 한 줄로 출력하라. 위치를 행·열 두 멤버를 가진 구조체로 만들고, 제자리에서 한 칸 움직이는 함수(또는 메서드)를 두자. 명령마다 움직이기 전에 prev = cur로 위치를 저장해 두고, 막히면 cur = prev로 되돌려 풀어 보자.

입력
첫 줄에 H와 W, 다음 H줄에 지도의 한 행씩(길이 W, 빈칸 없이), 마지막 줄에 명령 문자열이 주어진다.
1 ≤ H, W ≤ 100, 명령 문자열의 길이는 1 이상 100,000 이하다.
출력
한 줄: "행 열 부딪힌횟수"
예시 1 · stdin
3 4
S..#
.#..
....
RRRDDLLUR
stdout
2 1 2
main.py
입력(stdin)

실행하면 이 줄들이 차례로 input()·표준 입력으로 들어가요(실행 중에 묻지 않아요).

$ 준비됐어요

코드를 입력해 풀려면 PC에서 열어 주세요. 모바일에서는 문제와 풀이를 볼 수 있어요.

다른 언어로는?언어별 풀이 보기 · 3개 언어 풀이

이 문제는 C·C++·C#만 받아요.
대입하면 데이터가 통째로 복사되는 값 타입 구조체를 직접 만들 수 있는 게 이 셋이고, Python·JavaScript·TypeScript·Java의 객체와 크레이콘의 사전()은 대입하면 같은 것을 함께 가리키는 참조예요(그 언어들은 튜플이나 새 객체를 만들어 되돌려요).
C·C++의 Point prev = cur;와 C#의 struct Point에서 prev = cur는 행·열을 복사한 따로 있는 값이라, 그 뒤 cur를 제자리에서 움직여도 prev는 그대로 남아요.
C는 제자리에서 움직이려고 void step(Point *p, char d)처럼 포인터로 받아 p->r--로 쓰고 step(&cur, d)로 불러요.
C++와 C#은 멤버 함수(메서드)가 자기 자신을 바꿔요.
함정 넷: ① C#에서 struct를 class로 바꾸면 prev = cur가 같은 객체를 하나 더 가리킬 뿐이라, 움직이면 prev도 같이 움직이고 cur = prev는 아무것도 되돌리지 못해요.
오류도 없이 로봇이 벽 속으로 들어가요.
② C에서 Point *prev = &cur;처럼 주소를 쥐면 같은 일이 생겨요.
③ C++에서 Point &prev = cur;로 참조를 받아도 prev는 cur의 다른 이름일 뿐이에요.
④ C에서 void step(Point p, char d)처럼 값으로 받으면 이번에는 반대로 복사본만 움직여서 로봇이 처음 칸에서 꼼짝하지 않아요.

C#Main.cs · 43 줄
using System; struct Point  // 값 타입: 대입하면 R, C가 통째로 복사된다{    public int R, C;    public void Step(char d)    {        if (d == 'U') R--;        else if (d == 'D') R++;        else if (d == 'L') C--;        else C++;    }} class Program{    static void Main()    {        string[] t = Console.In.ReadToEnd().Split((char[])null, StringSplitOptions.RemoveEmptyEntries);        int h = int.Parse(t[0]), w = int.Parse(t[1]);        string[] grid = new string[h];        var cur = new Point();        for (int r = 0; r < h; r++)        {            grid[r] = t[2 + r];            int c = grid[r].IndexOf('S');            if (c >= 0) cur = new Point { R = r, C = c };        }        string moves = t[2 + h];        int bumps = 0;        foreach (char d in moves)        {            Point prev = cur;  // struct라서 복사본이 따로 생긴다            cur.Step(d);            if (cur.R < 0 || cur.R >= h || cur.C < 0 || cur.C >= w || grid[cur.R][cur.C] == '#')            {                cur = prev;                bumps++;            }        }        Console.WriteLine($"{cur.R + 1} {cur.C + 1} {bumps}");    }}
C++main.cpp · 39 줄
#include <iostream>#include <string>#include <vector> struct Point {    int r = 0, c = 0;    void step(char d) {  // 멤버 함수는 자기 자신(this)을 제자리에서 바꾼다        if (d == 'U') r--;        else if (d == 'D') r++;        else if (d == 'L') c--;        else c++;    }}; int main() {    std::ios::sync_with_stdio(false);    std::cin.tie(nullptr);    int h, w;    std::cin >> h >> w;    std::vector<std::string> grid(h);    Point cur;    for (int r = 0; r < h; r++) {        std::cin >> grid[r];        auto c = grid[r].find('S');        if (c != std::string::npos) cur = {r, static_cast<int>(c)};    }    std::string moves;    std::cin >> moves;    int bumps = 0;    for (char d : moves) {        Point prev = cur;  // 값 복사: prev는 cur와 상관없는 따로 있는 Point        cur.step(d);        if (cur.r < 0 || cur.r >= h || cur.c < 0 || cur.c >= w || grid[cur.r][cur.c] == '#') {            cur = prev;            bumps++;        }    }    std::cout << cur.r + 1 << ' ' << cur.c + 1 << ' ' << bumps << '\n';}
Cmain.c · 40 줄
#include <stdio.h>#include <string.h> typedef struct {    int r, c;} Point; static char grid[100][101];static char moves[100001]; /* 원본을 제자리에서 움직이려면 포인터로 받는다 */void step(Point *p, char d) {    if (d == 'U') p->r--;    else if (d == 'D') p->r++;    else if (d == 'L') p->c--;    else p->c++;} int main(void) {    int h, w;    scanf("%d %d", &h, &w);    Point cur = {0, 0};    for (int r = 0; r < h; r++) {        scanf("%100s", grid[r]);        char *s = strchr(grid[r], 'S');        if (s) cur = (Point){r, (int)(s - grid[r])};    }    scanf("%100000s", moves);    int bumps = 0;    for (int i = 0; moves[i]; i++) {        Point prev = cur;  /* 구조체 대입: r, c가 통째로 복사된 따로 있는 값 */        step(&cur, moves[i]);        if (cur.r < 0 || cur.r >= h || cur.c < 0 || cur.c >= w || grid[cur.r][cur.c] == '#') {            cur = prev;  /* 저장해 둔 복사본으로 되돌린다 */            bumps++;        }    }    printf("%d %d %d\n", cur.r + 1, cur.c + 1, bumps);    return 0;}