[BOJ] 3190 뱀

Eunyoung Han·2022년 10월 13일
0

https://www.acmicpc.net/problem/3190

해결 방법

그냥 냅다 구현이다. 근데 지문을 잘 읽어야 함

  • board는 다음과 같이 관리했다.
    • board[i][j] == 0 빈칸인 경우로, 뱀이 이곳에 온다면 머리를 옮기고 꼬리를 땡겨주어야 한다.
    • board[i][j] == 1 사과가 있는 경우로, 뱀이 이곳에 오면 머리만 옮겨주면 된다.
    • board[i][j] == -1 뱀의 몸통이 있는 자리이다. 뱀이 이곳에 오면 게임 끝
  • 머리 돌리기 배열 char l[10001]
    • 10000초까지 있다고 했으므로, 배열의 길이는 10001
    • l[i] : i 초에서 바꾸어야 할 방향
  • 방향 관리
    • 현재 방향의 인덱스 : d_idx
    • D : ( d_idx + 1 ) % 4
    • L : ( d_idx + 3 ) % 4
👉👇👈👆
dx010-1
dy10-10
  • 뱀 머리와 꼬리 관리
    • 처음엔 snake 구조체 안에 머리 위치, 꼬리 위치를 다 담아두려 했었다
      하지만 이 방법은 꼬리를 땡겨올 때 문제가 된다.. 꼬리를 땡기려면 꼬리 바로 앞 좌표를 알아야 하는데 그걸 따라가며 저장하기 쉽지 않다.
    • 그래서 바꾼 방법은 deque에 저장하는 것이었다.
      앞뒤로 넣고 빼기 쉽기 때문에, 머리와 꼬리 위치를 관리하는 데 적절하다고 생각했다.

종료 조건

난 while(1)에서 종료조건을 맞추기가 왜이렇게 힘든지 모르겠다 ^^,,
그래서 테스트케이스 2번의 답이 왜 20이 아니라 21인지 이해가 안됐다 ^.ㅜ

  • 처음 time은 0이다.
  • "현재" 머리 상태를 살폈을 때, 머리가 보드 바깥이라면 time을 리턴하고 break
    머리는 항상 몸의 일부이기 때문에 여기서 머리가 몸에 닿았는지 판단하는것은.. 의미없음
    그래서 머리를 이동시킬 때 살펴봐야 함
  • 머리를 이동시키는데 만약 다음 머리가 위치할 곳이 내 몸이라면
    다음 time에서 종료되어야 하므로 time+1을 리턴하고 break

실수한 부분

방향 변환을 먼저 하고 이동을 시켰다

다음 L개의 줄에는 뱀의 방향 변환 정보가 주어지는데, 정수 X와 문자 C로 이루어져 있으며. 게임 시작 시간으로부터 X초가 끝난 뒤에 왼쪽(C가 'L') 또는 오른쪽(C가 'D')로 90도 방향을 회전시킨다는 뜻이다.

방향 변환은 이동한 "후" 이루어져야 하는 동작이다.. 문제를 잘 읽자

소스 코드

#include <iostream>
#include <vector>
#include <queue> 
using namespace std;
#define pii pair<int,int>

int N,K,L;
const int n_ = 101;
int board[n_][n_]; // 1: 사과 0: 빈칸 -1: 뱀 
char l[10001];

int d_idx;
deque<pii> s;

const int dx[] = {0,1,0,-1};
const int dy[] = {1,0,-1,0};
 
bool in_board(int x, int y){
	return (0<=x && x<N && 0<=y && y<N);
} 

void print_board(){
	cout<<"-----";
	switch(d_idx){
		case 0 : cout<<"→"; break;
		case 1 : cout<<"↓"; break;
		case 2 : cout<<"←"; break;
		case 3 : cout<<"↑"; break; 
	}
	cout<<"-----\n";
	for(int i = 0; i<N; i++){
		for(int j = 0; j<N; j++){
			if(s.front().first == i && s.front().second == j) cout<<"*";
			cout<<board[i][j]<<"\t";
		}
		cout<<"\n";
	}
}

int main(){
	ios_base::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	
	cin>>N>>K;
	for(int i = 0; i<K; i++){
		int x,y; cin>>x>>y;
		board[x-1][y-1] = 1;
	}
	cin>>L;
	for(int i = 0; i<L; i++){
		int x; char c;
		cin>>x>>c;
		l[x] = c;
	}
	
	d_idx = 0;
	s.push_front({0,0});
	board[0][0] = -1;
	
	int time = 0;
	while(1){ 
		pii head = s.front();
		int x = head.first;
		int y = head.second;
		
		//현재 머리가 보드 밖 or 자신의 몸 -> break 
		if(!in_board(x,y)) {cout<<time<<"\n"; break;}
		
		int nx = x + dx[d_idx];
		int ny = y + dy[d_idx];
		
		//머리 이동
		if(board[nx][ny] == -1) {cout<<time+1<<"\n"; break;} 
		if(board[nx][ny] == 0) {
			pii tail = s.back();
			board[tail.first][tail.second] = 0;
			s.pop_back();
		}
		board[nx][ny] = -1;
		s.push_front({nx,ny});
		
		
		time++;
		
		//방향결정  
		if(l[time] == 'L') d_idx = (d_idx+3)%4;
		else if(l[time] == 'D') d_idx = (d_idx+1)%4;
	}
}

제출 결과

profile
HIU. CE / LG Elec.

0개의 댓글