본문 바로가기
programming/알고리즘 풀이

[SWEA] 1873. 상호의 배틀필드

by 몽구스_ 2021. 8. 5.
728x90

 

[SWEA] 1873. 상호의 배틀필드

 

 

다음 표는 게임 맵의 구성 요소를 나타낸다.

문자 의미
. 평지(전차가 들어갈 수 있다.)
* 벽돌로 만들어진 벽
# 강철로 만들어진 벽
- 물(전차는 들어갈 수 없다.)
^ 위쪽을 바라보는 전차(아래는 평지이다.)
v 아래쪽을 바라보는 전차(아래는 평지이다.)
< 왼쪽을 바라보는 전차(아래는 평지이다.)
> 오른쪽을 바라보는 전차(아래는 평지이다.)


다음 표는 사용자가 넣을 수 있는 입력의 종류를 나타낸다.
 

문자 동작
U Up : 전차가 바라보는 방향을 위쪽으로 바꾸고, 한 칸 위의 칸이 평지라면 위 그 칸으로 이동한다.
D Down : 전차가 바라보는 방향을 아래쪽으로 바꾸고, 한 칸 아래의 칸이 평지라면 그 칸으로 이동한다.
L Left : 전차가 바라보는 방향을 왼쪽으로 바꾸고, 한 칸 왼쪽의 칸이 평지라면 그 칸으로 이동한다.
R Right : 전차가 바라보는 방향을 오른쪽으로 바꾸고, 한 칸 오른쪽의 칸이 평지라면 그 칸으로 이동한다.
S Shoot : 전차가 현재 바라보고 있는 방향으로 포탄을 발사한다.

 

 

[입력]

첫 번째 줄에 테스트 케이스의 수 T가 주어진다.

각 테스트 케이스의 첫 번째 줄에는 두 정수 H, W (2 ≤ H, W ≤ 20) 이 공백으로 구분되어 주어진다.

이는 게임 맵의 높이가 H, 너비가 W임을 나타낸다.

즉, 게임 맵은 H x W크기의 격자판이다.

다음 H개의 각각의 줄에는 길이가 W인 문자열이 주어진다.

각각의 문자는 위의 게임 맵 구성 요소 표에 있는 문자들만 포함하며, 전차는 단 하나만 있다.

다음 줄에는 사용자가 넣을 입력의 개수를 나타내는 정수 N(0 < N ≤ 100) 이 주어진다.

다음 줄에는 길이가 N인 문자열이 주어진다.

각각의 문자는 위의 사용자가 넣을 수 있는 입력의 종류를 나타내는 표에 있는 문자들만 포함된다.


[출력]

각 테스트 케이스마다 ‘#x’(x는 테스트케이스 번호를 의미하며 1부터 시작한다)를 출력하고 한 칸을 띄운 후, 모든 입력을 처리하고 난 후의 게임 맵을 H개의 줄에 걸쳐 출력한다.

 

 

[풀이]

 

U,D,L,R 을 만나면 무조건 그자리에서 방향을 틀어주고 평지일 경우에만 그 방향으로 한칸 이동해준다.

이러한 상화좌우탐색을 위해 d 라는 2차원 배열을 설정해주고 이를 더한 변수를 인덱스로 지정해 이동해주었다.

S 은 공격행위인데 현재 전차가 있는 방향으로 포탄을 발사한다.

따라서 현재 전차 위치의 인덱스를 저장한 곳에서 전차가 어떤 방향인지 확인하고 그에 해당하는 d 인덱스를 가져온다.

포탄은 맵 배열 안에서 유효하며 벽 하나가 맞을 때까지 간다.

평지와  물을 만나면 계속 포탄은 이동하고 강철벽을 만나면 사라진다.

이를 위해 do while문으로 구성을 해주었다.

코드가 길어 복잡하게 느껴질 수 있지만 처음부터 차례대로 구현하는 시뮬레이션 문제이다.

 

 

public class al1873 {

	public static void main(String[] args) {
		
		Scanner sc = new Scanner(System.in);
		int T;
		T=sc.nextInt();
		
		int[][] d = {{-1,0},{1,0},{0,-1},{0,1}};
		HashMap<Character, Integer> map = new HashMap<>();
		map.put('^', 0);
		map.put('v', 1);
		map.put('<', 2);
		map.put('>', 3);
				
		for(int test_case = 1; test_case <= T; test_case++)
		{
			int r = sc.nextInt();
			int c = sc.nextInt();
			int ni = 0, nj = 0;
			
			char[][] arr = new char[r][c];
			
			for (int i = 0; i < r; i++) {
				arr[i] = sc.next().toCharArray();
				for (int j = 0; j < c; j++) {
					if(arr[i][j] == '<' || arr[i][j] == '>' || arr[i][j] == '^' || arr[i][j] == 'v') {
						ni = i;
						nj = j;
					}
				}
			}
			
			int n = sc.nextInt();
			String str = sc.next();
			int k = 0;
			int si = ni, sj = nj;
			int nr = 0, nc = 0;
			for (int i = 0; i < n; i++) {
				char ch = str.charAt(i);
				char go = '.';
				if(ch == 'U' || ch == 'D'|| ch == 'L' || ch == 'R') {
					if(ch == 'U') {
						go = '^';
						k = 0;
					}else if(ch == 'D') {
						go = 'v';
						k = 1;
					}else if(ch == 'L') {
						go = '<';
						k = 2;
					}else if(ch == 'R') {
						go = '>';
						k = 3;
					}
					arr[ni][nj] = go;
					nr = ni + d[k][0];
					nc = nj + d[k][1];
					if(nr >= 0 && nr < r && nc >= 0 && nc < c && arr[nr][nc] == '.') {
						arr[ni][nj] = '.';
						arr[nr][nc] = go;
						ni = nr;
						nj = nc;
					}
					si = ni;
					sj = nj;
				}else if(str.charAt(i) == 'S') {
					if(si >= 0 && si < r && sj >= 0 && sj < c && map.get(arr[si][sj]) != null){
						k = map.get(arr[si][sj]);
					}
					int count = 0;
					do {
						nr = si + d[k][0];
						nc = sj + d[k][1];
						if(nr >= 0 && nr < r && nc >= 0 && nc < c) {
							if(arr[nr][nc] == '*') {
								arr[nr][nc] = '.';
								count = 1;
							}else if(arr[nr][nc] == '#') {
								break;
							}

							si = nr;
							sj = nc;
						}else {
							break;
						}
					}while(count == 0);
				}
				
			}
			
			
			
			System.out.print("#" + test_case + " ");
			for (char[] ks : arr) {
				for (char ks2 : ks) {
					System.out.print(ks2);
				}
				System.out.println();
			}
			
		}

	}
}

 

  • 38,152 kb메모리
  • 226 ms실행시간
  • 3,861코드길이
  • Pass결과

'programming > 알고리즘 풀이' 카테고리의 다른 글

[백준(Baekjoon)] 2493. 탑  (0) 2021.08.10
[SWEA] 3499. 퍼펙트 셔플  (0) 2021.08.06
[SWEA] 1218. 괄호 짝짓기  (0) 2021.08.05
[SWEA] 2001. 파리 퇴치  (0) 2021.08.05
[SWEA] 2805. 농작물 수확하기  (0) 2021.08.04

댓글