https://www.swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AWXRF8s6ezEDFAUo

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

www.swexpertacademy.com

빈칸인 모든 칸으로부터  상하좌우 네 방향으로 모두 출발해보고 점수를 구하면된다. 그렇게 나온 점수 중 최댓값이 정답이다.

 

게임을 시작했으면 이동한 칸에 따라 처리해주면 된다.

 

1. 범위를 넘어간 경우(벽에 부딪힌 경우)에는 점수를 얻고 방향 전환 후에 바로 다음 칸으로 이동한다.

2. 출발 위치로 돌아오면 게임 종료

3. 블랙홀(-1)이면 게임 종료

4. 빈칸인 경우 계속 방향대로 이동

5. 블록인 경우(1~5)에는 각 블록의 방향에 맞게 방향을 전환해주고 점수를 얻는다.

6. 웜홀인 경우 같은 번호의 반대편 웜홀로 이동

 

 

웜홀의 경우에는 다음과 같이 x,y좌표를 가지는 벡터를 배열에 저장해서 구현하였다.

예를 들어 5번 웜홀의 좌표는 wormhole[0][0]과 wormhole[0][1]에 각각 들어있고, 6번 웜홀은 wormhole[1][0]과 wormhole[1][1]에 각각 들어있다. 게임판 배열에 들어있는 값에서 5를 빼준 값을 wormhole 배열의 인덱스로 사용하면 된다. (ex. 6번 웜홀의 인덱스는 1번)

 

wormhole 0(5번)

1(6번)

2(7번) 3(8번) 4(9번) 5(10번)
0 (x,y) (x,y) (x,y) (x,y) (x,y) (x,y)
1 (x,y) (x,y) (x,y) (x,y) (x,y) (x,y)

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
 
int n, ans;
int map[100][100];
int dx[] = { -1,0,1,0 };
int dy[] = { 0,1,0,-1 };
 
 
vector<pair<intint>> wormhole[5];
 
void start(int x, int y, int dir) {
 
    int point = 0;
    int nx = x;
    int ny = y;
    while (true) {
 
        //이동
        nx += dx[dir];
        ny += dy[dir];
 
        //벽에 부딪힘
        if (nx < 0 || ny < 0 || nx >= n || ny >= n) {
            point++;
 
            //반대 방향으로 바꿔준다.
            if (dir == 0 || dir == 1) {
                dir += 2;
            }
            else {
                dir -= 2;
            }
 
            //다음이동으로 바로 넘어감
            continue;
        }
 
 
        //출발위치로 돌아오면 게임 종료
        if (x == nx && y == ny) {
            break;
        }
 
        //블랙홀에 빠지면 게임 종료
        if (map[nx][ny] == -1) {
            break;
        }
 
        
        //빈칸이면 계속이동
        if (map[nx][ny] == 0continue;
 
 
        //블록인 경우
        if (map[nx][ny] == 1) {
            if (dir == 0 || dir == 1) {
                dir += 2;
            }
            else if (dir == 2) {
                dir = 1;
            }
            else {
                dir = 0;
            }
 
            point++;
        }
        else if (map[nx][ny] == 2) {
            if (dir == 1) {
                dir = 3;
            }
            else if (dir == 2) {
                dir = 0;
            }
            else if (dir == 3) {
                dir = 2;
            }
            else {
                dir = 1;
            }
 
            point++;
        }
        else if (map[nx][ny] == 3) {
            if (dir == 0) {
                dir = 3;
            }
            else if (dir == 1) {
                dir = 2;
            }
            else if (dir == 2) {
                dir = 0;
            }
            else {
                dir = 1;
            }
 
            point++;
        }
        else if (map[nx][ny] == 4) {
            if (dir == 0) {
                dir = 2;
            }
            else if (dir == 1) {
                dir = 0;
            }
            else if (dir == 2) {
                dir = 3;
            }
            else {
                dir = 1;
            }
 
            point++;
        }
        else if (map[nx][ny] == 5) {
            dir = (dir + 2) % 4;
            point++;
        } else if (map[nx][ny] >= 6 && map[nx][ny] <= 10) {
            //웜홀인 경우
            int num = map[nx][ny] - 6;
 
            //0번에 있는 좌표와 같으면 1번에 있는 좌표로 이동
            if (wormhole[num][0].first == nx && wormhole[num][0].second == ny) {
                nx = wormhole[num][1].first;
                ny = wormhole[num][1].second;
            }
            else { //1번에 있는 좌표와 같은 경우이므로 0번에 있는 좌표로 이동
                nx = wormhole[num][0].first;
                ny = wormhole[num][0].second;
            }
        }
    }
 
    //점수의 최대값을 저장
    if (ans < point) ans = point;
 
}
 
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
 
    int T;
    cin >> T;
    for (int tc = 1; tc <= T; tc++) {
        cin >> n;
 
        ans = 0;
        for (int i = 0; i < 5; i++) {
            wormhole[i].clear();
        }
 
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                cin >> map[i][j];
                
                //웜홀이면 벡터 배열에 저장
                if (map[i][j] >= 6 && map[i][j] <= 10) {
                    wormhole[map[i][j] - 6].push_back(make_pair(i, j));
                }
            }
        }
 
 
        //모든 빈칸에서 네방향으로 출발
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (map[i][j] != 0continue;
 
                for (int k = 0; k < 4; k++) {
                    start(i, j, k);
                }
 
            }
        }
 
        cout << '#' << tc << ' ' << ans << '\n';
    }
 
 
    return 0;
}
Colored by Color Scripter
 

https://www.swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AWXRF8s6ezEDFAUo

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

www.swexpertacademy.com

 

이 문제에서 어려웠던 부분은 웜홀 부분인 것 같다.

나는 웜홀의 좌표를 저장할 Wormhole클래스를 만들고 배열에 넣어주었다.

2차원 배열에 넣어서 각 6~10 번호마다 두 개씩 이므로 배열의 크기는 5X2가 된다. (웜홀은 쌍으로 존재하므로)

웜홀이 더 적게 존재할수도 있지만 최대 5개밖에 안되므로 그냥 한 번에 배열로 만들어줬다.

웜홀 배열의 각 좌표의 초기값을 -1로 설정해주고 이 점을 이용해서 두 개의 쌍을 차례대로 넣어준다.

 

예전에는 클래스를 만드는 대신에 3차원 int배열로 만들어 줬었다.(5X2X2 크기)

 

 

핀볼의 이동

  1. 출발 위치와 진행 방향을 임의로 설정하여 점수의 최댓값을 구하는 문제이므로 모든 빈 칸(값이 0인 칸)에서 각 네 방향으로 출발해서 모든 경우의 점수를 구한다.
  2. 각 이동에서는 블록의 모양에 따라서 적절히 방향을 잘 바꾸어 주며 이동시키고 블록이나 벽에 부딪힐 경우(범위 벗어나는 경우) 점수를 증가시킨다.
  3. 웜홀을 만난 경우에는 방향을 유지한 채 반대편 웜홀로 이동한다.
  4. 조건에 따라 핀볼이 출발 위치로 돌아오거나 블랙홀에 빠지는 경우가 될때까지 while문을 이용해 핀볼의 이동을 반복한다.
  5. 핀볼의 이동이 끝나면 그때의 점수를 현재 최대 점수와 비교해준다.

 

import java.io.*;
import java.util.*;

public class Solution {
	
	static class Wormhole {
		int x;
		int y;
		Wormhole(int x, int y) {
			this.x = x;
			this.y = y;
		}
	}
	
	static int N, max;
	static int[][] map;
	static int[] dx = {1,-1,0,0};
	static int[] dy = {0,0,1,-1};
	static Wormhole[][] holeArr;
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int T = Integer.parseInt(br.readLine());
		for(int tc=1; tc<=T; tc++) {
			N = Integer.parseInt(br.readLine());
			
			StringTokenizer st;
			map = new int[N][N];
			holeArr = new Wormhole[5][2];
			
            
            //웜홀의 위치 초기화 
			for(int i=0; i<5; i++) {
				for(int j=0; j<2; j++) {
					holeArr[i][j] = new Wormhole(-1,-1);
				}
			}
			
			for(int i=0; i<N; i++) {
				st = new StringTokenizer(br.readLine());
				for(int j=0; j<N; j++) {
					map[i][j] = Integer.parseInt(st.nextToken());
                    
                    //웜홀인 경우
                    //6번 웜홀부터 시작하므로 6번 웜홀이 0번째 index가 된다. 7번이 1, 8번이 2,,, 
					if(map[i][j] >= 6) {
                    
                    	//웜홀 첫 번째
						if(holeArr[map[i][j]-6][0].x == -1 && holeArr[map[i][j]-6][0].y == -1) {
							holeArr[map[i][j]-6][0].x = i;
							holeArr[map[i][j]-6][0].y = j;
						} else { //이미 첫 번째 웜홀의 위치가 저장되어 있는 경우 반대편 웜홀 저장
							holeArr[map[i][j]-6][1].x = i;
							holeArr[map[i][j]-6][1].y = j;
						}
					}
                    
				}
			}			
			
			max = 0;
			for(int i=0; i<N; i++) {
				for(int j=0; j<N; j++) {
                	
                    //빈칸이 아닌경우(블록이나 웜홀, 블랙홀인 경우)
					if(map[i][j] != 0) continue;
					
                    //상하좌우 각 방향으로 출발
					for(int k=0; k<4; k++) {
						move(i,j,k);
					}		
					
				}
			}
			
			System.out.println("#"+tc+" "+max);
		}
	}
	
	static void move(int x, int y, int dir) {
		
		int nx = x;
		int ny = y;
		int point = 0;
		
		while(true) {
        
        	//이동
			nx += dx[dir];
			ny += dy[dir];
			
            
            //벽에 부딪힌 경우 점수 증가하고 방향 전환
			if(nx < 0 || ny < 0 || nx >= N || ny >= N) {
				point++;
				if(dir == 0 || dir == 2) {
					dir++;
				} else {
					dir--;
				}

				continue;
			}
			
            
            //블랙홀에 빠짐
			if(map[nx][ny] == -1) {
				break;
			}
			
            
            //출발위치로 돌아옴
			if(x == nx && y == ny) {
				break;
			}
			
            
            
			if(map[nx][ny] == 0) {
            	//빈칸이므로 방향유지한채 바로 이동
				continue;
			} else if(map[nx][ny] == 1) { //각 블록의 종류에따라서 방향을 변환해주고 점수도 증가
				if(dir == 0) {
					dir = 2;
				} else if(dir == 1) {
					dir = 0;
				} else if(dir == 2) {
					dir = 3;
				} else {
					dir = 1;
				}
				
				point++;
				
			} else if(map[nx][ny] == 2) {
				if(dir == 0) {
					dir = 1;
				} else if(dir == 1) {
					dir = 2;
				} else if(dir == 2) {
					dir = 3;
				} else {
					dir = 0;
				}
				
				point++;
				
			} else if(map[nx][ny] == 3) {
				if(dir == 0) {
					dir = 1;
				} else if(dir == 1) {
					dir = 3;
				} else if(dir == 2) {
					dir = 0;
				} else {
					dir = 2;
				}
				
				point++;
				
			} else if(map[nx][ny] == 4) {
				if(dir == 0) {
					dir = 3;
				} else if(dir == 1) {
					dir = 0;
				} else if(dir == 2) {
					dir = 1;
				} else {
					dir = 2;
				}
				
				point++;
				
			} else if(map[nx][ny] == 5) {
				if(dir == 0 || dir == 2) {
					dir++;
				} else {
					dir--;
				}
				
				point++;
				
			} else { //웜홀인 경우 반대편 웜홀로 이동
				int holenum = map[nx][ny]-6;
				if(nx == holeArr[holenum][0].x && ny == holeArr[holenum][0].y) {
					nx = holeArr[holenum][1].x;
					ny = holeArr[holenum][1].y;
				} else {
					nx = holeArr[holenum][0].x;
					ny = holeArr[holenum][0].y;
				}
			}
		}
		
        
        //이동이 끝난 후에 점수 비교
		if(max < point) {
			max = point;
		}
	}

}

+ Recent posts