Problem
Problem URL : 뱀
[1] Answer Code (18. 10. 19)
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#define p pair<int,int>
using namespace std;
// 동 서 남 북
int dx[] = {0,0,1,-1};
int dy[] = {1,-1,0,0};
/*
Left : 0
Right : 1
[4] : 동 서 남 북
[2] : 다음 방향 위치 Index
ex) [1][0]은
(1,1)위치에서 현재 동쪽을 바라보고 있으며
Left Turn을 해야한다.
그러면
x = x + dx[2]
y = y + dy[2]
다음 위치는 (2,1)이 된다.
*/
int changeDir[4][2] = {
{3,2},
{2,3},
{0,1},
{1,0},
};
int map[105][105];
p turn_map[105][105];
int visit[105][105];
queue<p> q;
int n,k;
int t;
p tail_pos;
int tail_dir;
bool inRange(int x, int y){
if( x < 1 || x > n || y < 1 || y > n)
return false;
return true;
}
void print(){
for(int i=0; i<=n; i++)
cout << i%10 << " ";
cout << endl;
for(int i=1; i<=n-25; i++){
cout << i%10 << " " ;
for(int j=1; j<=n; j++){
if(visit[i][j] != 0)
cout << visit[i][j] << " ";
else
cout << " " << " ";
}
cout << endl;
}
cout << endl;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
t = 0;
cin >> n >> k;
for(int i=0; i<k; i++){
int a,b;
cin >> a >> b;
map[a][b] = 1;
visit[a][b] = 9;
}
int l;
cin >> l;
for(int i=0; i<l; i++){
int a;
char b;
cin >> a >> b;
/*
Left : 0
Right : 1
*/
if( b == 'D') // 오른쪽
q.push( p(a,1) );
else
q.push( p(a,0) );
}
tail_pos.first = 1;
tail_pos.second = 1;
tail_dir = 0;
int x = 1;
int y = 1;
int dir = 0;
while(1){
visit[x][y] = 1;
// cout << "time : " << t << endl;
// cout << "Head : " << x << " " << y << endl;
// cout << "Tail : " << tail_pos.first << " " << tail_pos.second << " " << tail_dir << endl;
// print();
if(!q.empty() && t == q.front().first){
dir = changeDir[dir][q.front().second];
q.pop();
turn_map[x][y] = p(dir,turn_map[x][y].second + 1);
}
t++;
x = x + dx[dir];
y = y + dy[dir];
if( visit[x][y] == 1 || ! inRange(x, y)){
break;
}
// 사과가 있을 경우
if(map[x][y] == 1){
// 사과 없애기
map[x][y] = 0;
// 머리만 이동
}
else{ // 꼬리 이동 후 머리 이동
// 가장 마지막 꼬리 영역 없애기
visit[tail_pos.first][tail_pos.second] = 0;
if(turn_map[tail_pos.first][tail_pos.second].second != 0){
tail_dir = turn_map[tail_pos.first][tail_pos.second].first;
turn_map[tail_pos.first][tail_pos.second].second--;
}
tail_pos.first += dx[tail_dir];
tail_pos.second += dy[tail_dir];
}
}
cout << t << endl;
return 0;
}
Review
-
삼성 역량 테스트 기출 문제
-
1) 우선 [ 시간 증가 / 이동 / 방향 전환 ] 3개를 올바른 순서로 배치시키는 부분이 까다로웠다.
-
2) 80 x 80 맵을 프린트하며 디버깅해서 문제를 찾았다. ㅂㄷㅂㄷ
-
3) 결론적으로 굉장히 어렵게 푼 듯 하다.
-
머리 / 꼬리를 나눠서 생각하다보니 복잡해졌다.
-
어떤 문제가 있었는지 살펴보자.
-
머리가 (1,1)에서 오른쪽으로 Turn을 한다.
-
이 때 turn_map[1][1]에는 오른쪽으로 Turn 하라는 값을 갖게 된다.
-
이후 다시 돌고 돌아 (1,1)에 와서 그냥 아래로 쭉 간다고 했을 때
-
turn_map[1][1]에는 처음에 오른쪽으로 Turn했기 때문에 오른쪽으로 가는 값을 갖고있게 된다.
-
그런데 머리를 따라가는 꼬리가 처음에 (1,1)에 갔을 때는 오른쪽으로 Turn하는게 맞는데
-
그 다음에는 아래로 쭉 내려가야한다.
-
하지만 turn_map[1][1]에는 오른쪽으로 가라고 말하기 때문에 꼬리는 아래로 내려가는게 아니라 오른쪽으로 가게 되는 문제가 발생한다.
[2] Answer Code (18. 10. 19)
#include<iostream>
#include<queue>
#define SIZE 101
#define EMPTY 0
#define APPLE 1
#define VISIT 2
using namespace std;
int N,K,L;
int arr[SIZE][SIZE];
queue< pair< int, int >>cmd;
int currentTime, currentDirection;
// 동 = 0 서 = 1 남 = 2 북 = 3
//[현재 방향] [D = 0 L = 1, D / L에 따른 다음 방향]
int dmove[4][2]={
{2,3},
{3,2},
{1,0},
{0,1}
};
int drow[4] = { 0,0,1,-1 };
int dcol[4] = { 1,-1,0,0 };
bool isOK(int row, int col)
{
return (0 < row && row <= N && 0 < col && col <= N);
}
int snakeMove()
{
queue< pair< int, int >>snake;
snake.push({ 1, 1 });
arr[1][1] = VISIT;
int row = 1;
int col = 1;
while (1)
{
int cmdTime = cmd.front().first;
int cmdDir = cmd.front().second;
// 방향 전환
if (cmdTime == currentTime)
{
cmd.pop();
currentDirection = dmove[currentDirection][cmdDir];
}
currentTime++;
row += drow[currentDirection];
col += dcol[currentDirection];
//기저 사례
if (isOK(row, col) == false) break; //벽 피해야함
if (arr[row][col] == VISIT) break; //몸통 피해야함
/*
사과가 없다면
큐에서 가장 마지막에 있었던 위치 값을 pop 후
그 위치에 더이상 꼬리가 없음을 표시한다.
(= arr에서 해당 좌표를 EMPTY 처리한다.)
*/
if (arr[row][col] == EMPTY)
{
int eraseRow = snake.front().first;
int eraseCol = snake.front().second;
arr[eraseRow][eraseCol] = EMPTY;
snake.pop();
}
snake.push({ row,col });
arr[row][col] = VISIT;
}
return currentTime;
}
int main()
{
scanf("%d",&N);
scanf("%d",&K);
int a, b; char c;
for (int i = 0; i < K; i++)
{
scanf("%d %d",&a,&b);
arr[a][b] = APPLE;
}
scanf("%d",&L);
for (int i = 0; i < L; i++)
{
scanf("%d %c",&a,&c);
if (c == 'D')
cmd.push({ a,0 });
else if (c == 'L')
cmd.push({ a,1 });
else
printf("error cmd");
}
printf("%d", snakeMove());
return 0;
}
Review
- 직접 푼 코드는 아니지만 너무나 깔끔하고 명료한 코드라서 기록해둔다.