재현이는 주변을 살펴보던 중 체스판과 말을 이용해서 새로운 게임을 만들기로 했다. 새로운 게임은 크기가 N×N인 체스판에서 진행되고, 사용하는 말의 개수는 K개이다. 말은 원판모양이고, 하나의 말 위에 다른 말을 올릴 수 있다. 체스판의 각 칸은 흰색, 빨간색, 파란색 중 하나로 색칠되어있다.
게임은 체스판 위에 말 K개를 놓고 시작한다. 말은 1번부터 K번까지 번호가 매겨져 있고, 이동 방향도 미리 정해져 있다. 이동 방향은 위, 아래, 왼쪽, 오른쪽 4가지 중 하나이다.
턴 한 번은 1번 말부터 K번 말까지 순서대로 이동시키는 것이다. 한 말이 이동할 때 위에 올려져 있는 말도 함께 이동한다. 말의 이동 방향에 있는 칸에 따라서 말의 이동이 다르며 아래와 같다. 턴이 진행되던 중에 말이 4개 이상 쌓이는 순간 게임이 종료된다.
체스판의 크기와 말의 위치, 이동 방향이 모두 주어졌을 때, 게임이 종료되는 턴의 번호를 구해보자.
첫째 줄에 체스판의 크기 N, 말의 개수 K가 주어진다. 둘째 줄부터 N개의 줄에 체스판의 정보가 주어진다. 체스판의 정보는 정수로 이루어져 있고, 각 정수는 칸의 색을 의미한다. 0은 흰색, 1은 빨간색, 2는 파란색이다.
다음 K개의 줄에 말의 정보가 1번 말부터 순서대로 주어진다. 말의 정보는 세 개의 정수로 이루어져 있고, 순서대로 행, 열의 번호, 이동 방향이다. 행과 열의 번호는 1부터 시작하고, 이동 방향은 4보다 작거나 같은 자연수이고 1부터 순서대로 →, ←, ↑, ↓의 의미를 갖는다.
같은 칸에 말이 두 개 이상 있는 경우는 입력으로 주어지지 않는다.
게임이 종료되는 턴의 번호를 출력한다. 그 값이 1,000보다 크거나 절대로 게임이 종료되지 않는 경우에는 -1을 출력한다.
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
|
#include <iostream>
#include <vector>
using namespace std;
int N,K;
class chess{
public:
int x, y, dir;
};
int MAP[13][13];
vector<int> V[13][13];
vector<chess> C;
bool check(){
for(int i=1;i<=N;i++)
for(int j=1;j<=N;j++)
if(V[i][j].size() >= 4)
return true;
return false;
}
void white(int idx, int nx, int ny);
void red(int idx, int nx, int ny);
void blue(int idx){
switch(C[idx].dir){
case 1:
C[idx].dir = 2;
break;
case 2:
C[idx].dir = 1;
break;
case 3:
C[idx].dir = 4;
break;
case 4:
C[idx].dir = 3;
break;
}
int dir = C[idx].dir;
int x = C[idx].x, y = C[idx].y;
int nx = x + "01102"[dir] - '1', ny = y + "02011"[dir] - '1';
if(nx<1||ny<1||ny> N||nx> N || MAP[nx][ny] == 2)
return ;
if(MAP[nx][ny] == 0){
white(idx, nx, ny);
}else if(MAP[nx][ny] == 1){
red(idx, nx, ny);
}
}
void red(int idx, int nx, int ny){
int x = C[idx].x, y = C[idx].y, start;
for(int j=0;j<V[x][y].size();j++)
if(V[x][y][j] == idx){
start = j;
break;
}
int end = V[x][y].size() - 1;
for(int i=end ;i>=start;i--){
V[nx][ny].push_back(V[x][y][i]);
C[V[x][y][i]].x = nx, C[V[x][y][i]].y = ny;
V[x][y].pop_back();
}
}
void white(int idx, int nx, int ny){
int x = C[idx].x, y = C[idx].y, start;
for(int j=0;j<V[x][y].size();j++)
if(V[x][y][j] == idx){
start = j;
break;
}
for(int i=start;i<V[x][y].size();i++){
V[nx][ny].push_back(V[x][y][i]);
C[V[x][y][i]].x = nx, C[V[x][y][i]].y = ny;
}
while(V[x][y].size() - start){
V[x][y].pop_back();
}
}
void move(int idx){
int x = C[idx].x, y = C[idx].y, dir = C[idx].dir;
int nx = x + "01102"[dir] - '1', ny = y + "02011"[dir] - '1';
if( nx<1 || ny<1 || ny> N|| nx> N || MAP[nx][ny] == 2){ //파란색 or 범위 오바
blue(idx);
}
else if(MAP[nx][ny] == 1){ //빨간색
red(idx, nx, ny);
}else if(MAP[nx][ny] == 0){ //흰색
white(idx, nx, ny);
}
}
int solve(){
int round = 1;
for(int i=0;i<1000;i++){
for(int idx=1;idx<=K;idx++){
move(idx);
if(check()) return round;
}
round++;
}
return -1;
}
int main(){
ios_base::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>N>>K;
for(int i=1;i<=N;i++)
for(int j=1;j<=N;j++)
cin>>MAP[i][j];
int x,y,dir;
chess c;
C.push_back(c);
for(int i=0;i<K;i++){
cin>>x>>y>>dir;
c.x = x, c.y = y, c.dir = dir;
V[x][y].push_back(i+1);
C.push_back(c);
}
cout<<solve();
return 0;
}
|
cs |
내일 삼성 대비로 상반기 기출 나온거 풀었다. 대략 두시간 좀 안걸린듯 내일은 더 빠르게 풀어야지
20057. 마법사 상어와 토네이도 Gold IV(C++) (0) | 2020.10.30 |
---|---|
16918. 봄버맨 (C++) SILVER I (0) | 2020.08.28 |
배열 돌리기 4 (C++) GOLD IV (0) | 2020.08.28 |
17140. ⚾ (C++) GOLD IV (0) | 2020.08.18 |
14891. 톱니바퀴(C++) SILVER I (0) | 2020.08.18 |
댓글 영역