접근

https://www.acmicpc.net/problem/17780

 

17780번: 새로운 게임

재현이는 주변을 살펴보던 중 체스판과 말을 이용해서 새로운 게임을 만들기로 했다. 새로운 게임은 크기가 N×N인 체스판에서 진행되고, 사용하는 말의 개수는 K개이다. 말은 원판모양이고, 하

www.acmicpc.net

문제에서 주어진 대로 구현만 하면 되는 단순 구현 문제였다. 백준에 삼성 관련 문제들이 이런 스타일인 것 같다.

문제의 키포인트는

  1. 맨 아래에 있는 말만 이동할 수 있다.
  2. 1번말부터 탐색하되 해당 말이 맨 아래에 있으면 이동하지 않고 넘어가면 된다.
  3. 하늘색 칸으로 이동 시 방향을 반대로 하고 1칸 이동하되, 반대쪽에도 하늘색 칸일 경우 방향만 바꾸고 제자리에 있는다. 맵 바깥으로 나가는 경우도 하늘색 칸에 도달한 것과 동일하게 계산한다.
  4. 목적 칸이 흰색일 경우 아래의 말부터 다음 칸으로 이동시키고, 빨간색일 경우 맨 위 말부터 다음 칸으로 이동시킨다.

위 포인트들에 주의하면서 풀면 쉽게 해결할 수 있다.

코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Main {

  static class Horse {

    int num, dir;

    Horse(int num, int dir) {
      this.num = num;
      this.dir = dir;
    }
  }

  static int N, K;
  static int color[][], loc[][];
  static LinkedList<Horse>[][] map;
  static int[] dr = { 0, -1, 0, 1 };
  static int[] dc = { 1, 0, -1, 0 };

  public static void main(String[] args) throws IOException {
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    StringTokenizer st = new StringTokenizer(br.readLine());
    N = Integer.parseInt(st.nextToken());
    K = Integer.parseInt(st.nextToken());

    // color[r][c]에 해당 칸의 색을 저장
    color = new int[N][N];
    for (int i = 0; i < N; i++) {
      st = new StringTokenizer(br.readLine());
      for (int j = 0; j < N; j++) {
        color[i][j] = Integer.parseInt(st.nextToken());
      }
    }
    // loc[k][0], loc[k][1] 에 k번 말의 r, c 좌표 저장
    loc = new int[K][2];
    // map[r][c] 에 LinkedList를 만들어 말의 순서 정보 저장
    map = new LinkedList[N][N];
    for (int i = 0; i < N; i++) {
      for (int j = 0; j < N; j++) {
        map[i][j] = new LinkedList<>();
      }
    }
    int r, c, d;
    for (int i = 0; i < K; i++) {
      st = new StringTokenizer(br.readLine());
      r = Integer.parseInt(st.nextToken()) - 1;
      c = Integer.parseInt(st.nextToken()) - 1;
      d = Integer.parseInt(st.nextToken()) - 1;
      switch (d) {
        case 1:
          d = 2;
          break;
        case 2:
          d = 1;
          break;
        default:
          break;
      }
      loc[i][0] = r;
      loc[i][1] = c;
      map[r][c].add(new Horse(i, d));
    }
    br.close();
    System.out.println(Solve());
  }

  static int Solve() {
    for (int t = 1; t <= 1000; t++) {
      for (int k = 0; k < K; k++) {
        int r = loc[k][0];
        int c = loc[k][1];
        // k번 말이 맨 아래에 있지 않을 경우 continue
        if (map[r][c].get(0).num != k) continue;
        int d = map[r][c].get(0).dir;
        int nr = r + dr[d];
        int nc = c + dc[d];
        // 다음 위치가 하늘색 칸 혹은 체스 판을 벗어날 경우
        if (colorBlue(nr, nc)) {
          d = (d + 2) % 4;
          map[r][c].get(0).dir = d;
          nr = r + dr[d];
          nc = c + dc[d];
          // 뒤돌아 한칸 이동한 위치도 하늘색 칸 혹은 체스 판을 벗어날 경우 continue
          if (colorBlue(nr, nc)) {
            continue;
          }
        }
        // r, c 위치의 말들을 nr, nc 위치로 옮기고 해당 칸의 말의 수가 4 이상이면 t 리턴
        if (moveAndCount(r, c, nr, nc) >= 4) {
          return t;
        }
      }
    }
    // 1000회 이동하고도 조건에 만족하지 않으면 -1 리턴
    return -1;
  }

  // r, c 위치가 하늘색 칸이거나 체스판 밖으로 나갔는지 판단하는 함수
  static boolean colorBlue(int r, int c) {
    return r < 0 || N <= r || c < 0 || N <= c || color[r][c] == 2;
  }

  // r, c 위치의 말을 nr, nc 위치로 옮기고 해당 칸의 말의 수를 리턴하는 함수
  static int moveAndCount(int r, int c, int nr, int nc) {
    if (color[nr][nc] == 0) {
      while (map[r][c].size() > 0) {
        Horse temp = map[r][c].pollFirst();
        loc[temp.num][0] = nr;
        loc[temp.num][1] = nc;
        map[nr][nc].add(temp);
      }
    } else {
      while (map[r][c].size() > 0) {
        Horse temp = map[r][c].pollLast();
        loc[temp.num][0] = nr;
        loc[temp.num][1] = nc;
        map[nr][nc].add(temp);
      }
    }
    return map[nr][nc].size();
  }
}

더 생각해 볼 것?

...

코드나 내용 관련 조언, 부족한 점 및 질문 언제든 환영합니다!

반응형
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기