본문 바로가기
나도 공부한다/알고리즘

[백준] 16113. 시그널 (C++)

by 꾸빵이 2024. 6. 15.

Key

예외처리를 신경써줘야한다. 나의 경우엔 한가지 조건을 빠트려서 반례 첫번째 케이스부터 틀렸었다.

 

Idea

코드는 짧지만 아이디어를 생각해내는데 많은 시간이 걸렸다.

특히 푼 사람이 1000명도 안 되는 문제라 참고할 수 있는 풀이도 많지 않았다...

시그널 길이가 최대 10만이라 저장 안하고 푸는 방법을 생각해봤는데 방법이 없는 것 같다.

 

그래서 생각했던 방법이 N/5크기로 끊어서 저장한 후, 가로줄을 검사하며 #(검정)이 나오면 세로줄을 검사하는 것이다.

이 방법을 사용하면 0, 1, 6, 8과 5, 9는 두번째 줄도 검사하여야한다는 단점이 있었다.

또한, 1의 경우 가로 길이가 1이고 나머지는 3이라 다음 숫자를 찾을 때 1은 1칸을 건너뛰고 나머지 숫자는 3칸을 건너뛴다는 규칙성이 있는데, 내가 생각한 방법을 쓰면 두번째 줄을 검사하는 숫자들은 2칸을 건너뛰고 나머지는 3칸, 1은 1칸을 건너뛴다는 새로운 규칙이 생겨 복잡하다. 여러 조건을 고려해봤을 때 문제 난이도에 비해 로직이 복잡해진다는 생각이 들었다.  

 

 

결국 건너뛰어야하는 칸 수가 1인 것과 1이 아닌 것으로 나뉘어지므로 그 규칙에 따라 1과 1이 아닌 것부터 분류하기로 했다. 1이 아닌 경우에는 5X3칸을 result에 저장하고 미리 저장해둔 숫자별 시그널과 비교하여 어떤 숫자인지 판별했다.

 

70%쯤에서 오답이 떴는데, i==N/5-1, 즉 맨 뒷칸이 #인 경우에 무조건 1이라는 것을 생각하지 못해서 틀렸다. 

이 조건을 추가해주지 않으면 다음 케이스에서는 11이 아니고 1이 출력된다.

'1이 아닌 경우'로 빠지는데 숫자별 시그널에 1 데이터가 없기 때문에 아무것도 추가가 안 되는 것이다.

25
#...##...##...##...##...#



#...#

#...#

#...#

#...#

#...#

 

Code

#include <iostream>
#include <vector>
#include <map>
using namespace std;

int N;
string input;

map < string, string >numbers = {
	{"####.##.##.####", "0"},
	{"###..#####..###", "2"},
	{"###..####..####","3"},
	{"#.##.####..#..#","4"},
	{"####..###..####", "5"},
	{"####..####.####", "6"},
	{"###..#..#..#..#", "7"},
	{"####.#####.####", "8"},
	{"####.####..####", "9"},
};

int main() {

	cin >> N >> input;

	vector<string>v;

	for (int i = 0; i < N; i += N / 5) {
		v.push_back(input.substr(i, N / 5));
	}

	int plus = 1;
	string answer = "";

	for (int i = 0; i < N/5; i+=plus) {

		plus = 1;

		// 검은색 발견하면 무슨 숫자인지 검사
		if (v[0][i] == '#') {
			// 1인 경우
			string result = "";
			if (i==N/5-1 || v[0][i + 1] == '.' && v[3][i] == '#') {
				answer += '1';
			}
			// 1이 아닌 경우
			else {
				for (int j = 0; j < 5; j++) {
					result += v[j].substr(i, 3);
				}
				plus = 3;
				if (numbers.find(result) != numbers.end()) {
					answer += numbers[result];
				}
			}

			
		}
		
	}

	cout << answer << "\n";

	return 0;
}