[문제]
코드트리 | 코딩테스트 준비를 위한 알고리즘 정석
국가대표가 만든 코딩 공부의 가이드북 코딩 왕초보부터 꿈의 직장 코테 합격까지, 국가대표가 엄선한 커리큘럼으로 준비해보세요.
www.codetree.ai
[설명]
읽을때부터 좀 그랬는데 생각보다 까다로웠던 문제였다. 소용돌이로 가는건 해봤는데 돌아오는 건 또 안해봤구나...구현자체는 빨리했는데 예외처리할게 좀 많았다.
까다로웠던 것들은
- 0,0에 도착했을때 방향전환 후 처리과정
- 거꾸로 돌때는 두번째부터 이동거리 감소됨 (첫번째 아래로 갈때는 오른쪽으로 가는 횟수 안줄어듬...)
- 바로 방향전환한다! 라는 것을 인지못하고 마지막으로 오른쪽 방향을 향했을때 count++을 하는 실수 등.이거때문에 한참 해멨다.
- 또 바보같이 턴수를 의미하는 t 을 while문에서 돌게해서 오류가있었다. for문 마다 t를 넣고 나가는 조건도 for문마다 넣어줘서 해결했다.
[코드]
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
#define X first
#define Y second
int N, M, H, K;
int dx[4] = {-1,0,1,0};
int dy[4] = {0,1,0,-1}; //상, 우, 하, 좌
int board[100][100];
int dis[100][100];
int score;
int t;
pair <int, int> chaser;
int c_dir; //술래 방향
struct runner {
int num;
int x, y;
int dir; //dir: 1 우, 2: 하
bool out;
};
vector <runner> runners;
void runner_move(runner me) {
if (dis[me.x][me.y] <= 3) {
int nx = me.x + dx[me.dir];
int ny = me.y + dy[me.dir];
if (nx < 0 || nx >= N || ny < 0 || ny >= N) { //격자밖
me.dir = (me.dir + 2) % 4;
nx = me.x + dx[me.dir];
ny = me.y + dy[me.dir];
}
if (nx == chaser.X && ny == chaser.Y) {
runners[me.num] = me;
return;
}
else {
if (board[me.x][me.y] > 0) board[me.x][me.y]--; // 이전 좌표의 사람 한병 감소
me.x = nx;
me.y = ny;
if (board[me.x][me.y] >= 0) board[me.x][me.y]++; // 이전 좌표의 사람 한병 감소
runners[me.num] = me;
}
}
}
void BFS() {
bool vis[101][101] = { false, };
queue <pair<int, int>> q;
dis[chaser.X][chaser.Y] = 0;
q.push(chaser);
while (!q.empty()) {
pair <int, int> cur = q.front();
q.pop();
for (int i = 0; i < 4; i++) {
int nx = cur.X + dx[i];
int ny = cur.Y + dy[i];
if (vis[nx][ny]) continue;
if (nx < 0 || nx >= N || ny < 0 || ny >= N) continue;
dis[nx][ny] = dis[cur.X][cur.Y] + 1;
vis[nx][ny] = true;
q.push({ nx,ny });
}
}
}
void check_runner() {
int count = 1;
pair <int, int> cur = chaser;
while (true) {
if (board[cur.X][cur.Y] > 0) {
score += board[cur.X][cur.Y] * t;
board[cur.X][cur.Y] = 0;
for (int i = 0; i <= M; i++) {
if (runners[i].x == cur.X && runners[i].y == cur.Y && !runners[i].out)
runners[i].out = true;
}
}
cur.X = cur.X + dx[c_dir];
cur.Y = cur.Y + dy[c_dir];
if (cur.X < 0 || cur.X >= N || cur.Y < 0 || cur.Y >= N) return;
if(count == 3) return;
count++;
}
}
int main() {
cin >> N >> M >> H >> K;
runners.push_back({ 0,0,0,0,true });
int x, y, d;
for (int i = 1; i <= M; i++) {
cin >> x >> y >> d;
runners.push_back({ i,x-1,y-1,d,false });
board[x -1][y-1] = 1;
}
for (int i = 0; i < H; i++) {
cin >> x >> y;
board[x-1][y-1] = -1;
}
t = 1;
c_dir = 0;
int change = 1;
bool go = true;
bool back = false;
bool first = false;
chaser = { N / 2 , N / 2 }; //술래 좌표
while (true) {
if(go) {
for (int i = 0; i < change; i++) {
if (t == K + 1) {
cout << score;
return 0;
}
BFS();
for (int j = 1; j <= M; j++) {
if (!runners[j].out)
runner_move(runners[j]);
}
chaser.X = chaser.X + dx[c_dir];
chaser.Y = chaser.Y + dy[c_dir]; //바로 움직임
if (chaser.X == 0 && chaser.Y == 0) {
c_dir = 2;
check_runner();
back = true;
go = false;
change = N-1;
first = false;
t++;
break;
}
if (i == change - 1)
c_dir = (c_dir + 1) % 4; //도착하자마자 방향바뀜.
check_runner();
t++;
}
if (c_dir == 2 || c_dir == 0)
{
if(!back)
change++;
}
}
if (back) {
for (int i = 0; i < change; i++) {
if (t == K + 1) {
cout << score;
return 0;
}
BFS();
for (int j = 1; j <= M; j++) {
if (!runners[j].out)
runner_move(runners[j]);
}
chaser.X = chaser.X + dx[c_dir];
chaser.Y = chaser.Y + dy[c_dir]; //바로 움직임
if (chaser.X == N / 2 && chaser.Y == N / 2) {
c_dir = 0;
check_runner();
back = false;
go = true;
change = 1;
first = false;
t++;
break;
}
if (i == change - 1)
{
c_dir = (c_dir - 1);
if(c_dir < 0) c_dir = 3;
}
check_runner();
t++;
}
if ((c_dir == 3 || c_dir == 1) && !go)
{
if(first) change--;
first = true;
}
}
}
}
'알고리즘 문제 풀이 > 삼성 SW 역량 테스트' 카테고리의 다른 글
[코드트리] 팩맨 (C++) (0) | 2024.04.14 |
---|---|
[코드트리] 나무박멸 (C++) (1) | 2024.04.13 |
[코드트리] 싸움땅 (C++) (0) | 2024.04.12 |
[코드트리] 코드트리 빵 (C++) (1) | 2024.04.12 |
[코드트리] 포탑 부수기 (C++) (0) | 2024.04.12 |
[문제]
코드트리 | 코딩테스트 준비를 위한 알고리즘 정석
국가대표가 만든 코딩 공부의 가이드북 코딩 왕초보부터 꿈의 직장 코테 합격까지, 국가대표가 엄선한 커리큘럼으로 준비해보세요.
www.codetree.ai
[설명]
읽을때부터 좀 그랬는데 생각보다 까다로웠던 문제였다. 소용돌이로 가는건 해봤는데 돌아오는 건 또 안해봤구나...구현자체는 빨리했는데 예외처리할게 좀 많았다.
까다로웠던 것들은
- 0,0에 도착했을때 방향전환 후 처리과정
- 거꾸로 돌때는 두번째부터 이동거리 감소됨 (첫번째 아래로 갈때는 오른쪽으로 가는 횟수 안줄어듬...)
- 바로 방향전환한다! 라는 것을 인지못하고 마지막으로 오른쪽 방향을 향했을때 count++을 하는 실수 등.이거때문에 한참 해멨다.
- 또 바보같이 턴수를 의미하는 t 을 while문에서 돌게해서 오류가있었다. for문 마다 t를 넣고 나가는 조건도 for문마다 넣어줘서 해결했다.
[코드]
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
#define X first
#define Y second
int N, M, H, K;
int dx[4] = {-1,0,1,0};
int dy[4] = {0,1,0,-1}; //상, 우, 하, 좌
int board[100][100];
int dis[100][100];
int score;
int t;
pair <int, int> chaser;
int c_dir; //술래 방향
struct runner {
int num;
int x, y;
int dir; //dir: 1 우, 2: 하
bool out;
};
vector <runner> runners;
void runner_move(runner me) {
if (dis[me.x][me.y] <= 3) {
int nx = me.x + dx[me.dir];
int ny = me.y + dy[me.dir];
if (nx < 0 || nx >= N || ny < 0 || ny >= N) { //격자밖
me.dir = (me.dir + 2) % 4;
nx = me.x + dx[me.dir];
ny = me.y + dy[me.dir];
}
if (nx == chaser.X && ny == chaser.Y) {
runners[me.num] = me;
return;
}
else {
if (board[me.x][me.y] > 0) board[me.x][me.y]--; // 이전 좌표의 사람 한병 감소
me.x = nx;
me.y = ny;
if (board[me.x][me.y] >= 0) board[me.x][me.y]++; // 이전 좌표의 사람 한병 감소
runners[me.num] = me;
}
}
}
void BFS() {
bool vis[101][101] = { false, };
queue <pair<int, int>> q;
dis[chaser.X][chaser.Y] = 0;
q.push(chaser);
while (!q.empty()) {
pair <int, int> cur = q.front();
q.pop();
for (int i = 0; i < 4; i++) {
int nx = cur.X + dx[i];
int ny = cur.Y + dy[i];
if (vis[nx][ny]) continue;
if (nx < 0 || nx >= N || ny < 0 || ny >= N) continue;
dis[nx][ny] = dis[cur.X][cur.Y] + 1;
vis[nx][ny] = true;
q.push({ nx,ny });
}
}
}
void check_runner() {
int count = 1;
pair <int, int> cur = chaser;
while (true) {
if (board[cur.X][cur.Y] > 0) {
score += board[cur.X][cur.Y] * t;
board[cur.X][cur.Y] = 0;
for (int i = 0; i <= M; i++) {
if (runners[i].x == cur.X && runners[i].y == cur.Y && !runners[i].out)
runners[i].out = true;
}
}
cur.X = cur.X + dx[c_dir];
cur.Y = cur.Y + dy[c_dir];
if (cur.X < 0 || cur.X >= N || cur.Y < 0 || cur.Y >= N) return;
if(count == 3) return;
count++;
}
}
int main() {
cin >> N >> M >> H >> K;
runners.push_back({ 0,0,0,0,true });
int x, y, d;
for (int i = 1; i <= M; i++) {
cin >> x >> y >> d;
runners.push_back({ i,x-1,y-1,d,false });
board[x -1][y-1] = 1;
}
for (int i = 0; i < H; i++) {
cin >> x >> y;
board[x-1][y-1] = -1;
}
t = 1;
c_dir = 0;
int change = 1;
bool go = true;
bool back = false;
bool first = false;
chaser = { N / 2 , N / 2 }; //술래 좌표
while (true) {
if(go) {
for (int i = 0; i < change; i++) {
if (t == K + 1) {
cout << score;
return 0;
}
BFS();
for (int j = 1; j <= M; j++) {
if (!runners[j].out)
runner_move(runners[j]);
}
chaser.X = chaser.X + dx[c_dir];
chaser.Y = chaser.Y + dy[c_dir]; //바로 움직임
if (chaser.X == 0 && chaser.Y == 0) {
c_dir = 2;
check_runner();
back = true;
go = false;
change = N-1;
first = false;
t++;
break;
}
if (i == change - 1)
c_dir = (c_dir + 1) % 4; //도착하자마자 방향바뀜.
check_runner();
t++;
}
if (c_dir == 2 || c_dir == 0)
{
if(!back)
change++;
}
}
if (back) {
for (int i = 0; i < change; i++) {
if (t == K + 1) {
cout << score;
return 0;
}
BFS();
for (int j = 1; j <= M; j++) {
if (!runners[j].out)
runner_move(runners[j]);
}
chaser.X = chaser.X + dx[c_dir];
chaser.Y = chaser.Y + dy[c_dir]; //바로 움직임
if (chaser.X == N / 2 && chaser.Y == N / 2) {
c_dir = 0;
check_runner();
back = false;
go = true;
change = 1;
first = false;
t++;
break;
}
if (i == change - 1)
{
c_dir = (c_dir - 1);
if(c_dir < 0) c_dir = 3;
}
check_runner();
t++;
}
if ((c_dir == 3 || c_dir == 1) && !go)
{
if(first) change--;
first = true;
}
}
}
}
'알고리즘 문제 풀이 > 삼성 SW 역량 테스트' 카테고리의 다른 글
[코드트리] 팩맨 (C++) (0) | 2024.04.14 |
---|---|
[코드트리] 나무박멸 (C++) (1) | 2024.04.13 |
[코드트리] 싸움땅 (C++) (0) | 2024.04.12 |
[코드트리] 코드트리 빵 (C++) (1) | 2024.04.12 |
[코드트리] 포탑 부수기 (C++) (0) | 2024.04.12 |