이것이 코딩 테스트다 :: Part2 :: Chapter 4 :: 구현

Embedded June·2020년 8월 23일
0

<모든 문제는 C++를 기반으로 풀이한다.>

구현 부분 문제 풀이 및 해설

1. 상하좌우

  • 푸는 방법은 여러가지겠지만 여기서는 switch-case문을 사용한 직관적인 방법을 사용했다.
  • 맵을 구현할 필요가 전혀 없다. 출발지 좌표 (1, 1)을 기준으로 좌표값만 조작해주면 된다.
  • 이 문제에서 가장 까다로운건 입력받는 명령어 개수가 정해져있지 않다는 점이다.
    do { } while (getc(stdin) == ' ')을 사용해도 좋지만, 여기서는 각 명령어가 띄어쓰기로 구분되어 있어서 제대로 입력을 받지 못한다.
  • 따라서, getline(cin, buffer) 함수를 이용해서 각 명령어를 하나씩 따로따로 받아오자.
  • PS를 할 때 2차원 좌표는 굉장히 햇갈리기 쉬운 요소다.
    아예 본인이 정해두고 한 가지 방법으로만 풀자. 나는 (y, x)로 푸는 방법을 선호한다.
    • U는 위로 이동해야하므로 x를 증가시키고, D는 x를 감소시킨다.
    • L은 왼쪽으로 이동해야하므로 y를 감소시키고, R은 y를 증가시킨다.
#include <iostream>
using namespace std;

int main() {
	ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
	int N = 0;	cin >> N;	cin.ignore();	// getline() 함수 쓰기 위해서 버퍼 비우기.
	int curX = 1, curY = 1;

	string plan; getline(cin, plan);		// 아예 string으로 입력받아버리기.
	for (int i = 0; i < plan.size(); ++i) {
		char order = plan[i];
		switch (order) {
		case 'U':
			if (curX != 1) curX--;
			break;
		case 'D':
			if (curX != N) curX++;
			break;
		case 'L':
			if (curY != 1) curY--;
			break;
		case 'R':
			if (curY != N) curY++;
			break;
		}
	}
	cout << curX << ' ' << curY << '\n';
} 

2. 시각

  • 시, 분, 초를 모두 문자열로 생각해서 bruteforce 돌리면 된다.
  • 최악의 경우라 할지라도 20×60×60=72,00020 \times 60 \times 60 = 72,000 이라 충분히 시간내에 돌아간다.
#include <iostream>
using namespace std;

int main() {
	ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
	int N = 0;	cin >> N;
	int cnt = 0;
	for (int i = 0; i <= N; ++i)
		for (int j = 0; j < 60; ++j)
			for (int k = 0; k < 60; ++k)
				if ((to_string(i) + to_string(j) + to_string(k)).find('3') != string::npos) cnt++;
	cout << cnt << '\n';
} 
  • concat 된 문자열에서 3이 없을 경우 find() 함수는 string::npos를 반환함을 기억하자.

3. 왕실의 나이트

  • 임의의 점 (y, x)에서 나이트가 갈 수 있는 모든 방향의 변위를 고려해준다.
  • for문을 사용해서 8방향에 대해 갈 수 있는지 여부를 검사한다.
  • 갈 수 있는 경우를 카운트한 뒤 출력해주면 된다.
// EX 02 :: 왕실의 나이트 
#include <iostream>
using namespace std;

static constexpr int moving[8][2] {
	{1, -2}, {2, -1}, {2, 1}, {1, 2},
	{-1, 2}, {-2, 1}, {-2, -1}, {-1, -2}
};	// 나이트의 이동경로 변위를 (y, x)로 나타냄.

inline bool isInner(int y, int x, int num) {
	int newY = y + moving[num][0], newX = x + moving[num][1];
	return ((1 <= newY && newY <= 8) && (1 <= newX && newX <= 8));
}

int main() {
	ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
	string initPos;	cin >> initPos;
	// 알파벳은 열(col)을 의미, 숫자는 행(row)을 의미하고, 1을 더해줘야 한다.
	int x = initPos[1] - '1' + 1, y = initPos[0] - 'a' + 1;

	int ans = 0;
	for (int i = 0; i < 8; ++i)	// 8방향 모두 테스트
            	if (isInner(y, x, i)) ans++; 
	cout << ans << '\n';
} 
  • 필자는 (y, x)로 푸는것을 선호하므로 나이트가 놓인 좌표를 위 주석과 같은 방법으로 구했다. 각자 원하는 방식대로 하는 것을 추천한다.

4. 개임 개발

  • 삼성코테에서 선호하는 문제 유형이라고 해서 열심히 풀었다.
  • 문제에서 주어진 조건대로만 그대로 코드로 구현하면 된다. 설명할 부분이 딱히 없다.
// EX 03 :: 개임 개발
#include <iostream>
using namespace std;

static constexpr int moving[4][2] {
	{-1, 0}, {0, 1}, {1, 0}, {0, -1}
};	// 북쪽	   동쪽	   남쪽	   서쪽
static int N, M, curX, curY, pos, map[50][50];	// 0: 육지, 1: 바다, 2: 방문
enum class state {land, ocean, visited};

int solve() {
	int ret = 1;
	map[curY][curX] = static_cast<int>(state::visited);	// 첫 칸을 방문표시 해준다.
	
	while(true) {
		int returnCnt = 0;
		for (int i = 0; i < 4; ++i) {
			pos = (pos - 1 < 0) ? 3 : pos - 1;	// 현재 방향의 왼쪽 방향으로 바꿔준다.
		 	// 맵의 외곽은 항상 바다, 범위 검사 불필요하다.
			if (map[curY + moving[pos][0]][curX + moving[pos][1]] == static_cast<int>(state::land)) {
				curY += moving[pos][0], curX += moving[pos][1];
				map[curY][curX] = static_cast<int>(state::visited);	// 방문 표시한다.
				ret++;
				break;
			}
			else returnCnt++;	// 갈 수 없다면 방향만 바꾸고 돌아가기 카운트 하나 증감.
		}
		if (returnCnt == 4) {	// 더 이상 갈 곳이 없다면 뒤로 이동해야한다.
			curY -= moving[pos][0], curX -= moving[pos][1];
			// 뒷칸이 바다일 경우 더 이상 이동할 수 없으므로 움직임 종료.
			if (map[curY][curX] == static_cast<int>(state::ocean)) break;
		}
	}
	return ret;
}

int main() {
	ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
	cin >> N >> M;
	cin >> curX >> curY >> pos;
	
	for (int y = 0; y < N; ++y)
		for (int x = 0; x < M; ++x)
			cin >> map[y][x];
	cout << solve() << '\n';
} 
  • 문제 조건은 3가지지만 공통적인 부분을 뽑아낸다면 결국 어쨋든 방향은 왼쪽 방향으로 바뀐다이다. 따라서 갈 수 있든 없든 무조건 방향은 바꿔주고, 4방향에 대해 모두 갈 수 없는 경우 뒤로 한 칸 이동한다. 이때 이동한 곳이 바다라면 반복문을 종료한다.
profile
임베디드 시스템 공학자를 지망하는 컴퓨터공학+전자공학 복수전공 학부생입니다. 타인의 피드백을 수용하고 숙고하고 대응하며 자극과 반응 사이의 간격을 늘리며 스스로 반응을 컨트롤 할 수 있는 주도적인 사람이 되는 것이 저의 20대의 목표입니다.

0개의 댓글