새로운게임 2
문제 해석
- 체스판의 말을 움직여서 쌓인 말의 개수가 4개 이상이 되기 위한 시간을 출력하는 문제입니다.
-
말들을 모두 움직이는데 이동하려는 칸에 따라 다음과 같이 변화합니다.
-
이동하려는 칸이 흰색인 경우
해당 말 위에 있는 모든 말을과 같이 다음 칸으로 이동합니다. 이동하려는 칸에 말이 쌓여있는 경우, 그대로 이어서 쌓으면 됩니다.
-
빨간색인 경우
흰색과 같이 이동하고, 말이 쌓인 순서를 반대로 바꿉니다.
-
파란색 or 범위를 벗어나는 경우
이동방향을 반대로 하고 이동하였을 때, 그 칸 또한 파란색 or 범위를 벗어나면 방향만 바꾸고 이동하지 않습니다.
위의 경우가 아니면 a,b 조건으로 이동합니다.
-
설계(20)
- 각 말의 위치(x,y)와 이동방향을 기록하는 1차원 배열을 두고, 각 말이 이동할 때마다 위치와 방향을 갱신시켜줍니다.
- 2차원 벡터를 통해 말을 쌓을 수 있게 합니다.
- 이동할 칸이 파란색이거나 범위가 벗어나는 경우를 우선적으로 검사해서 이동방향을 바꿔준 후, 한번더 조사를 했을 시 위와 같은 조건에 또 걸리게 되면 진행하지 않도록 합니다.
- 이동시간(T) <= 1000 이므로, O(T*(K^2))의 시간복잡도로 그냥 구현을 해도 테스트를 통과하기에 충분한 시간입니다.
구현(60)
코드
#include <iostream>
#include <vector>
using namespace std;
#define MAXN 12
struct node {
int x;
int y;
int dir;
};
node horse[10];
int dx[] = { 0,0,-1,1 };
int dy[] = { 1,-1,0,0 };
vector<int> map[MAXN][MAXN];
int arr[MAXN][MAXN];
int N, K;
bool is_range(int x, int y) {
if (x < 0 || y < 0 || x >= N || y >= N) return false;
return true;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int ans = 0;
cin >> N >> K;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
cin >> arr[i][j];
}
}
for (int i = 0; i < K; i++) {
int x, y, dir;
cin >> x >> y >> dir;
x--;
y--;
dir--;
horse[i] = { x,y,dir };
map[x][y].push_back(i);
}
while (ans <= 1000) {
ans++;
for (int i = 0; i < K; i++) {
int x = horse[i].x;
int y = horse[i].y;
int dir = horse[i].dir;
int start;
for (start = 0; start < map[x][y].size(); start++) {
if (map[x][y][start] == i) break;
}
int nx = x + dx[dir];
int ny = y + dy[dir];
if (!is_range(nx, ny) || arr[nx][ny] == 2) {
if (dir <= 1) {
dir = 1 - dir;
}
else {
dir = (3 - dir) + 2;
}
horse[i] = { x,y,dir };
nx = x + dx[dir];
ny = y + dy[dir];
}
if (!is_range(nx, ny) || arr[nx][ny] == 2) {
horse[i] = { x,y,dir };
continue;
}
// 이동할 칸이 흰색인 경우
if (arr[nx][ny] == 0) {
int num = map[x][y].size() - start;
for (int j = start; j < map[x][y].size(); j++) {
int idx = map[x][y][j];
horse[idx].x = nx;
horse[idx].y = ny;
map[nx][ny].push_back(idx);
}
while (num--) map[x][y].pop_back();
if (map[nx][ny].size() >= 4) {
cout << ans << "\n";
return 0;
}
}
// 이동할 칸이 빨간색인 경우
else if (arr[nx][ny] == 1) {
int num = map[x][y].size() - start;
while (num!=0) {
int idx = map[x][y].back();
horse[idx].x = nx;
horse[idx].y = ny;
map[nx][ny].push_back(idx);
map[x][y].pop_back();
num--;
}
if (map[nx][ny].size() >= 4) {
cout << ans << "\n";
return 0;
}
}
}
}
cout << -1 << "\n";
return 0;
}
디버깅
- 지문을 읽을 때, 말이 맨 아래에 있는 경우에만 이동이 가능한 것으로 착각을 하여 디버깅을 하는데 시간이 오래 걸렸습니다.
제출결과
0ms
마무리
지문을 꼼꼼하게 읽지 않으면 함정에 빠지기 쉬운문제이기 때문에 구현력을 키우는데 아주 좋은 문제인 것 같습니다.