728x90

https://programmers.co.kr/learn/courses/30/lessons/42883

 

코딩테스트 연습 - 큰 수 만들기

 

programmers.co.kr

일단 이렇게 풀었는데 너무 복잡하게 푼 것 같아서 다시 풀어봐야겠다.

#include <string>
#include <vector>

using namespace std;

string solution(string number, int k) {
	int n = 0;
	int targetLength = number.length() - k;
	int length = number.length();
	string targetStr = "";
	bool flag = false;
	int maxNum = -1;
	int maxIndex;
	while (true) {
		for (int i = 0; i <= length - targetLength; i++) {
			if (stoi(number.substr(i, 1)) > maxNum) {
				maxNum = stoi(number.substr(i, 1));
				maxIndex = i;
				if (maxNum == 9)
					break;
			}
		}
		targetStr += number[maxIndex];
		number.erase(0, maxIndex + 1);
		length -= maxIndex;
		if (targetStr.length() == targetLength)
			break;
		maxNum = 0;
		maxIndex = 0;
	}
	return targetStr;
}
728x90

'알고리즘 문제' 카테고리의 다른 글

[프로그래머스] 행렬의 곱셈  (0) 2020.08.01
[프로그래머스] 기능개발  (0) 2020.07.31
[프로그래머스] 땅따먹기  (0) 2020.07.30
[프로그래머스] 폰켓몬  (0) 2020.07.28
[백준] 1780번 종이의 개수  (0) 2020.04.11
728x90

https://programmers.co.kr/learn/courses/30/lessons/12913

 

코딩테스트 연습 - 땅따먹기

땅따먹기 게임을 하려고 합니다. 땅따먹기 게임의 땅(land)은 총 N행 4열로 이루어져 있고, 모든 칸에는 점수가 쓰여 있습니다. 1행부터 땅을 밟으며 한 행씩 내려올 때, 각 행의 4칸 중 한 칸만 밟��

programmers.co.kr

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

int solution(vector<vector<int> > land) {
	for (int i = 1; i < land.size(); i++) {
		land[i][0] = land[i][0] + max(max(land[i - 1][1], land[i - 1][2]), land[i - 1][3]);
		land[i][1] = land[i][1] + max(max(land[i - 1][0], land[i - 1][2]), land[i - 1][3]);
		land[i][2] = land[i][2] + max(max(land[i - 1][0], land[i - 1][1]), land[i - 1][3]);
		land[i][3] = land[i][3] + max(max(land[i - 1][0], land[i - 1][1]), land[i - 1][2]);
	}
	return max(max(max(land[land.size() - 1][0], land[land.size() - 1][1]), land[land.size() - 1][2]), land[land.size() - 1][3]);
}

동적계획법으로 풀었다. 메모리는 따로 사용하지 않았고 주어진 이차원 벡터에 그대로 덮어썼다.

(i행 0열)에 왔다는 것은 i - 1행에서는 0열이 아닌 1열 또는 2열 또는 3열을 거쳤다는 것이기 때문에 (i행 0열)의 값에 (i - 1행 1열), (i - 1행 2열), (i - 1행 3열) 중 최댓값을 더해주었다. 그러면 land[i][0]에는 i행 0열까지 오는 경로 중 가장 최댓값을 가질 수 있는 경로로 왔을 때의 점수가 저장되어있는 것이다. 그런식으로 누적해서 더해서 land[마지막 행]에는 각 열의 최댓값 4개가 저장되어 있다. (4열이기 때문) 그 4개의 숫자 중에서 최댓값이 정답이 된다.

728x90

'알고리즘 문제' 카테고리의 다른 글

[프로그래머스] 기능개발  (0) 2020.07.31
[프로그래머스] 큰 수 만들기  (0) 2020.07.30
[프로그래머스] 폰켓몬  (0) 2020.07.28
[백준] 1780번 종이의 개수  (0) 2020.04.11
[백준] N M 찍기  (0) 2020.04.11
728x90

https://programmers.co.kr/learn/courses/30/lessons/1845

 

코딩테스트 연습 - 폰켓몬

당신은 폰켓몬을 잡기 위한 오랜 여행 끝에, 홍 박사님의 연구실에 도착했습니다. 홍 박사님은 당신에게 자신의 연구실에 있는 총 N 마리의 폰켓몬 중에서 N/2마리를 가져가도 좋다고 했습니다. �

programmers.co.kr

#include <vector>
#include <set>

using namespace std;

int solution(vector<int> nums) {
	set<int> s;
	for (int i = 0; i < nums.size(); i++) {
		s.insert(nums[i]);
	}
	if (s.size() <= nums.size() / 2) {
		return s.size();
	}
	else {
		return nums.size() / 2;
	}
}

일단 이렇게 set으로 간단하게 풀었다. vector를 set으로 복사하는 함수를 몰라서 일단 저렇게 for문을 돌려서 풀고나서 vector를 set으로 복사하는 방법을 찾아봤다.

http://www.cplusplus.com/reference/set/set/set/

 

set::set - C++ Reference

range (2)template set (InputIterator first, InputIterator last, const key_compare& comp = key_compare(), const allocator_type& = allocator_type()); template set (InputIterator first, InputIterator last, const allocator_type& = allocator_type());

www.cplusplus.com

여기에 있는 생성자들 중 range에 해당하는 방법으로 vector의 원소들을 원소로 가지는 set으로 만들 수 있다.

만약 v라는 int 타입의 vector가 있고 그것의 원소들을 원소로 가지는 set s을 만들고 싶다면

set<int> s(v.begin(), v.end());

이렇게 하면 된다.

 

따라서 이 방법을 이용해서 폰켓몬을 풀면 코드가 다음과 같이 더 짧아진다.

#include <vector>
#include <set>

using namespace std;

int solution(vector<int> nums) {
	set<int> s(nums.begin(), nums.end());
	if (s.size() <= nums.size() / 2) {
		return s.size();
	}
	else {
		return nums.size() / 2;
	}
}
728x90

'알고리즘 문제' 카테고리의 다른 글

[프로그래머스] 큰 수 만들기  (0) 2020.07.30
[프로그래머스] 땅따먹기  (0) 2020.07.30
[백준] 1780번 종이의 개수  (0) 2020.04.11
[백준] N M 찍기  (0) 2020.04.11
[백준] 10815번 숫자 카드  (0) 2020.04.11
728x90

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

 

1780번: 종이의 개수

N×N크기의 행렬로 표현되는 종이가 있다. 종이의 각 칸에는 -1, 0, 1의 세 값 중 하나가 저장되어 있다. 우리는 이 행렬을 적절한 크기로 자르려고 하는데, 이때 다음의 규칙에 따라 자르려고 한다. 만약 종이가 모두 같은 수로 되어 있다면 이 종이를 그대로 사용한다. (1)이 아닌 경우에는 종이를 같은 크기의 9개의 종이로 자르고, 각각의 잘린 종이에 대해서 (1)의 과정을 반복한다. 이와 같이 종이를 잘랐을 때, -1로만 채워진 종이의 개수, 0으

www.acmicpc.net

분할정복으로 9등분을 해가면서 풀면 된다.

그 나눠진 부분의 전체가 같은 수라면 재귀호출을 하지 않고 나눠진 부분에 있는 수들이 모두 같지 않으면 재귀호출을 해서 또 9등분을 하는 식으로 풀었따.

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

vector<vector<int>> v;
int minusOne = 0;
int zero = 0;
int one = 0;

void divide(int rowStart, int rowEnd, int colStart, int colEnd, int width) {
	int first = v[rowStart][colStart];
	bool flag = true;
	if (width != 1) {
		for (int i = rowStart; i <= rowEnd; i++) {
			for (int j = colStart; j <= colEnd; j++) {
				if (first != v[i][j]) {
					flag = false;
					break;
				}
			}
			if (!flag)
				break;
		}
	}
	if (flag) {
		if (first == -1) {
			minusOne++;
		}
		else if (first == 0) {
			zero++;
		}
		else if (first == 1) {
			one++;
		}
	}
	else {
		divide(rowStart, rowStart + width / 3 - 1, colStart, colStart + width / 3 - 1, width / 3);
		divide(rowStart + width / 3, rowStart + width / 3 + width / 3 - 1, colStart, colStart + width / 3 - 1, width / 3);
		divide(rowStart + width / 3 + width / 3, rowEnd, colStart, colStart+ width / 3 - 1, width / 3);

		divide(rowStart, rowStart + width / 3 - 1, colStart + width / 3, colStart + width / 3 + width / 3 - 1, width / 3);
		divide(rowStart + width / 3, rowStart + width / 3 + width / 3 - 1, colStart + width / 3, colStart + width / 3 + width / 3 - 1, width / 3);
		divide(rowStart + width / 3 + width / 3, rowEnd, colStart + width / 3, colStart + width / 3 + width / 3 - 1, width / 3);

		divide(rowStart, rowStart + width / 3 - 1, colStart + width / 3 + width / 3, colEnd, width / 3);
		divide(rowStart + width / 3, rowStart + width / 3 + width / 3 - 1, colStart + width / 3 + width / 3, colEnd, width / 3);
		divide(rowStart + width / 3 + width / 3, rowEnd, colStart + width / 3 + width / 3, colEnd, width / 3);
	}
}

int main() {
	int n;
	cin >> n;
	v = vector<vector<int>>(n, vector<int>(n));
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			cin >> v[i][j];
		}
	}
	divide(0, n - 1, 0, n - 1, n);
	cout << minusOne << endl;
	cout << zero << endl;
	cout << one << endl;
	return 0;
}
728x90

'알고리즘 문제' 카테고리의 다른 글

[프로그래머스] 땅따먹기  (0) 2020.07.30
[프로그래머스] 폰켓몬  (0) 2020.07.28
[백준] N M 찍기  (0) 2020.04.11
[백준] 10815번 숫자 카드  (0) 2020.04.11
[백준] 1158번 요세푸스 문제  (0) 2020.04.11
728x90

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

 

18883번: N M 찍기

총 N개의 줄을 출력해야 한다. 각 줄에는 M개의 정수를 공백 한 칸으로 구분해 출력해야 한다. 1번 줄에는 1부터 M까지, 2번 줄에는 M+1부터 2×M까지, ..., N번 줄에는 (N-1)×M+1부터 N×M까지 출력해야 한다. 모든 줄의 시작과 끝에 공백이 있으면 안되고, 모든 줄은 줄바꿈(\n)으로 끝나야 한다.

www.acmicpc.net

num이라는 변수를 후위 연산자로 증가시키며 출력했다.

주의할 것은 줄 끝에 공백이 있으면 안 된다. 따라서

if(j == m - 1)

이렇게 조건문으로 행의 마지막 숫자 뒤에는 바로 '\n'으로 줄바꿈을 하도록 했다.

#include <iostream>
using namespace std;

int main() {
	int n, m;
	cin >> n >> m;
	int num = 1;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			if (j == m - 1)
				cout << num++ << '\n';
			else
				cout << num++ << " ";
		}
	}
	return 0;
}
728x90

'알고리즘 문제' 카테고리의 다른 글

[프로그래머스] 폰켓몬  (0) 2020.07.28
[백준] 1780번 종이의 개수  (0) 2020.04.11
[백준] 10815번 숫자 카드  (0) 2020.04.11
[백준] 1158번 요세푸스 문제  (0) 2020.04.11
[백준] 4949번 균형잡힌 세상  (0) 2020.04.08
728x90

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

 

10815번: 숫자 카드

첫째 줄에 상근이가 가지고 있는 숫자 카드의 개수 N(1 ≤ N ≤ 500,000)이 주어진다. 둘째 줄에는 숫자 카드에 적혀있는 정수가 주어진다. 숫자 카드에 적혀있는 수는 -10,000,000보다 크거나 같고, 10,000,000보다 작거나 같다. 두 숫자 카드에 같은 수가 적혀있는 경우는 없다. 셋째 줄에는 M(1 ≤ M ≤ 500,000)이 주어진다. 넷째 줄에는 상근이가 가지고 있는 숫자 카드인지 아닌지를 구해야 할 M개의 정수가 주어지며, 이

www.acmicpc.net

정렬을 해놓은 후 이진탐색(이분검색)을 이용하면 된다. 

그리고 많은 수를 입력받고 많은 수를 출력해야 하기 때문에 입출력 시간을 줄이는 다음 코드를 써줘야 한다.

ios_base::sync_with_stdio(false);
cin.tie(NULL);

정렬하는 것은 <algorithm> 헤더의 sort() 함수를 이용하고 이진탐색은 binary_search() 함수를 이용하면 된다.

이 함수들의 사용법을 자세히 알고 싶다면 아래 링크에서 볼 수 있다.

 

https://breakcoding.tistory.com/117

 

[C++] vector (벡터) 정렬, 배열 정렬하기

정렬을 하려면 라이브러리의 sort() 함수를 쓰면 된다. 따라서 헤더파일을 포함해줘야 한다. sort() 함수의 첫번째 두번째 매개변수는 iterator, 즉 포인터이다. sort - C++ Reference cu..

breakcoding.tistory.com

https://breakcoding.tistory.com/188

 

[C++] 이진탐색 binary_search, upper_bound, lower_bound 함수 사용법

C++로 코딩을 하다가 이진탐색을 할 필요가 있다면 직접 구현할 필요없이 헤더에 정의되어 있는 binary_search() 함수를 사용하면 된다. C++에서 이진탐색을 어떻게 하는지 알아보자. 일단 이진탐색이..

breakcoding.tistory.com

코드는 다음과 같다.

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

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	int n;
	cin >> n;
	vector<int> v(n);
	for (int i = 0; i < v.size(); i++) {
		cin >> v[i];
	}
	sort(v.begin(), v.end());
	int m;
	cin >> m;
	vector<bool> result(m);
	for (int i = 0; i < m; i++) {
		int temp;
		cin >> temp;
		result[i] = binary_search(v.begin(), v.end(), temp);
	}
	for (int i = 0; i < m; i++) {
		cout << result[i] << " ";
	}
	return 0;
}
728x90

'알고리즘 문제' 카테고리의 다른 글

[백준] 1780번 종이의 개수  (0) 2020.04.11
[백준] N M 찍기  (0) 2020.04.11
[백준] 1158번 요세푸스 문제  (0) 2020.04.11
[백준] 4949번 균형잡힌 세상  (0) 2020.04.08
[백준] 2589번 보물섬  (0) 2020.04.07
728x90

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

 

1158번: 요세푸스 문제

첫째 줄에 N과 K가 빈 칸을 사이에 두고 순서대로 주어진다. (1 ≤ K ≤ N ≤ 5,000)

www.acmicpc.net

벡터에 일단 1~N을 저장해놓고 직접 지워가며 시뮬레이션하며 풀었다. 이 과정을 벡터가 빌 때까지 반복해주었다.

원형 연결리스트처럼 동작하게 하기 위해 modulo 연산을 사용해주었다.

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

int main() {
	int n, k;
	cin >> n >> k;
	vector<int> v(n);
	for (int i = 0; i < n; i++) {
		v[i] = i + 1;
	}
	vector<int> result;
	int start = 0;
	while (!v.empty()) {
		int index = (start + k - 1) % v.size();
		result.push_back(v[index]);
		v.erase(v.begin() + index);
		if(!v.empty())
			start = index % v.size();
	}
	cout << "<";
	for (int i = 0; i < result.size(); i++) {
		cout << result[i];
		if (i == result.size() - 1) {
			cout << ">";
		}
		else {
			cout << ", ";
		}
	}
	return 0;
}

start 변수는 K번째를 세기 시작하는 곳이다. start부터 K번째 위치를 지우면 된다.

그런데 지우고 나서가 문제이다. start로부터 K번째 위치가 index라고 하면 지우고 나서 이 위치가 start가 되면 안 된다.

예를 들어 벡터의 크기가 8이었다고 하자. 그리고 start가 5, K가 3이어서 지워야 할 위치인 index가 7이었다고 하자. 그래서 인덱스가 7인 원소를 삭제했다고 하자. 그러면 벡터의 크기는 8에서 7로 줄어드는데 그러면 인덱스 7은 벡터의 범위를 벗어났으므로 index out of range 에러가 날 것이다. 따라서 현재 vector 크기로 한 번 더 modulo 연산을 해줘야 한다.

 

728x90

'알고리즘 문제' 카테고리의 다른 글

[백준] N M 찍기  (0) 2020.04.11
[백준] 10815번 숫자 카드  (0) 2020.04.11
[백준] 4949번 균형잡힌 세상  (0) 2020.04.08
[백준] 2589번 보물섬  (0) 2020.04.07
[백준] 2630번 색종이 만들기  (0) 2020.03.30
728x90

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

 

4949번: 균형잡힌 세상

문제 세계는 균형이 잘 잡혀있어야 한다. 양과 음, 빛과 어둠 그리고 왼쪽 괄호와 오른쪽 괄호처럼 말이다. 정민이의 임무는 어떤 문자열이 주어졌을 때, 괄호들의 균형이 잘 맞춰져 있는지 판단하는 프로그램을 짜는 것이다. 문자열에 포함되는 괄호는 소괄호("()") 와 대괄호("[]")로 2종류이고, 문자열이 균형을 이루는 조건은 아래와 같다. 모든 왼쪽 소괄호("(")는 오른쪽 소괄호(")")와만 짝을 이뤄야 한다. 모든 왼쪽 대괄호("[")는 오른쪽 대괄

www.acmicpc.net

이렇게 괄호의 짝이 맞는지를 알아보는 문제는 스택을 사용하면 된다.

우선 코드는 다음과 같이 짰다.

#include <iostream>
#include <string>
#include <stack>
using namespace std;


int main() {
	while (true) {
		string s;
		getline(cin, s);
		bool flag = true;
		if (s == ".")
			break;
		stack<char> st;
		for (int i = 0; i < s.size(); i++) {
			if (s[i] == '(') {
				st.push('(');
			}
			else if (s[i] == '[') {
				st.push('[');
			}
			else if (s[i] == ')') {
				if (st.empty()) {
					flag = false;
					break;
				}
				if (st.top() == '(') {
					st.pop();
				}
				else {
					flag = false;
					break;
				}
			}
			else if (s[i] == ']') {
				if (st.empty()) {
					flag = false;
					break;
				}
				if (st.top() == '[') {
					st.pop();
				}
				else {
					flag = false;
					break;
				}
			}
		}
		if (!flag)
			cout << "no\n";
		else {
			if(!st.empty())
				cout << "no\n";
			else
				cout << "yes\n";
		}
	}
	return 0;
}

'('를 만나면 스택에 push하고 ')'를 만나면 스택에서 pop하고 그 pop된게 '('가 아니라면 짝이 맞지 않는 것이다.

'['도 마찬가지로 '['를 만나면 스택에 push하고 ']'를 만나면 스택에서 pop하고 그 pop된게 '['가 아니라면 짝이 맞지 않는 것이다.

짝이 맞지 않다는 것을 발견했다면 굳이 문자열의 끝까지 돌 필요가 없으므로 break를 해서 for문을 빠져나온다.

그 전에 짝이 맞지 않는 문자열이라는 것을 표시하기 위해 flag 변수를 false로 바꿔준다.

for문 바깥에서 flag가 true인지 false인지 확인해보고 false라면 no를 출력한다.

하지만 flag가 true라고 해서 무조건 yes를 출력하면 안 된다.

주의할 점은 문자열의 끝까지 다 잘 돌고 나서도 스택이 비어있는지를 반드시 확인해야 한다.

이 코드로 따졌을 때 flag가 true라고 하더라도 스택이 비어있지 않으면 no를 출력해야 한다.

728x90

'알고리즘 문제' 카테고리의 다른 글

[백준] 10815번 숫자 카드  (0) 2020.04.11
[백준] 1158번 요세푸스 문제  (0) 2020.04.11
[백준] 2589번 보물섬  (0) 2020.04.07
[백준] 2630번 색종이 만들기  (0) 2020.03.30
[백준] 5086번 배수와 약수  (0) 2020.03.30
728x90

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

 

2589번: 보물섬

보물섬 지도를 발견한 후크 선장은 보물을 찾아나섰다. 보물섬 지도는 아래 그림과 같이 직사각형 모양이며 여러 칸으로 나뉘어져 있다. 각 칸은 육지(L)나 바다(W)로 표시되어 있다. 이 지도에서 이동은 상하좌우로 이웃한 육지로만 가능하며, 한 칸 이동하는데 한 시간이 걸린다. 보물은 서로 간에 최단 거리로 이동하는데 있어 가장 긴 시간이 걸리는 육지 두 곳에 나뉘어 묻혀있다. 육지를 나타내는 두 곳 사이를 최단 거리로 이동하려면 같은 곳을 두 번 이상 지

www.acmicpc.net

최단경로를 구하는 것이기 때문에 BFS(너비 우선 탐색)로 풀면 된다. 가중치가 없는 그래프에서 최단경로를 구하라고 하면 무조건 BFS이다. 이 지도에서는 상하좌우 어디든 비용이 1이므로 가중치가 없다고 할 수 있다.

일단 코드는 다음과 같다.

#include <iostream>
#include <vector>
#include <queue>
#include <tuple>
using namespace std;


int main() {
	int n, m;
	cin >> n >> m;
	vector<vector<char>> map(n, vector<char>(m));
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			cin >> map[i][j];
		}
	}
	int maxDistance = 0;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			if (map[i][j] == 'L') {
				queue<tuple<int, int, int>> q;
				vector<vector<bool>> visited(n, vector<bool>(m));
				q.push(make_tuple(i, j, 0));
				while (!q.empty()) {
					tuple<int, int, int> cur = q.front();
					q.pop();
					int row = get<0>(cur);
					int col = get<1>(cur);
					if (!visited[row][col]) {
						if (get<2>(cur) > maxDistance)
							maxDistance = get<2>(cur);
						visited[row][col] = true;
						if (row + 1 < n && map[row + 1][col] == 'L' && !visited[row + 1][col]) {
							q.push(make_tuple(row + 1, col, get<2>(cur) + 1));
						}
						if (row - 1 >= 0 && map[row - 1][col] == 'L' && !visited[row - 1][col]) {
							q.push(make_tuple(row - 1, col, get<2>(cur) + 1));
						}
						if (col + 1 < m && map[row][col + 1] == 'L' && !visited[row][col + 1]) {
							q.push(make_tuple(row, col + 1, get<2>(cur) + 1));
						}
						if (col - 1 >= 0 && map[row][col - 1] == 'L' && !visited[row][col - 1]) {
							q.push(make_tuple(row, col - 1, get<2>(cur) + 1));
						}
					}
				}
			}
		}
	}
	cout << maxDistance;
	return 0;
}

육지인 칸이라면 매 칸마다 BFS를 하면 된다. BFS를 하기 위해 큐를 사용했고 큐에는 tuple 객체를 만들어 넣어주었다.

튜플의 첫 번째 원소는 행, 두 번째 원소는 열, 세 번째 원소에는 BFS를 시작한 그 칸에서 여기까지의 거리를 저장해주었다. 그리고 최대 거리를 maxDistance에 저장하며 갱신해주었다.

상하좌우를 탐색하기만 하면 된다. 다른 BFS와 조금 다른 점은 보통 BFS는 특정 지점에서 특정 지점으로 가는 최단경로를 구하는 것이기 때문에 visited 배열도 하나만 필요했고 다 공유했다. 하지만 이 문제에서는 특정 지점에서 특정 지점으로 가는 것이 아니라 어느 지점인지 모르는 지점에서 어느 지점인지 모르는 지점까지의 최단경로 중 최장경로를 찾는 것이기 때문에 모든 육지에서 나머지 육지로 가는 모든 경우의 수를 구해야 한다. 따라서 한 칸마다 BFS를 새로 시작하기 때문에 매 칸마다 그 칸을 위한 visited 배열도 새로 만들고 queue도 새로 만들어줘야 한다.

728x90
728x90

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

 

2630번: 색종이 만들기

첫째 줄에는 전체 종이의 한 변의 길이 N이 주어져 있다. N은 2, 4, 8, 16, 32, 64, 128 중 하나이다. 색종이의 각 가로줄의 정사각형칸들의 색이 윗줄부터 차례로 둘째 줄부터 마지막 줄까지 주어진다. 하얀색으로 칠해진 칸은 0, 파란색으로 칠해진 칸은 1로 주어지며, 각 숫자 사이에는 빈칸이 하나씩 있다.

www.acmicpc.net

분할 정복 문제로, 재귀로 풀면 된다.

#include <iostream>
#include <vector>
using namespace std;
vector<vector<int>> v;

int white = 0;
int blue = 0;

void divide(int startRow, int startCol, int endRow, int endCol) {
	//cout << startRow << "~" << endRow << "행 " << startCol << "~" << endCol << "열" << endl;
	int color = v[startRow][startCol];
	bool flag = true;
	for (int i = startRow; i <= endRow; i++) {
		for (int j = startCol; j <= endCol; j++) {
			if (v[i][j] != color) {
				flag = false;
				break;
			}
		}
		if(!flag)
			break;
	}
	if (!flag) {
		//cout << "한 덩어리로 안 됨" << endl;
		divide(startRow, startCol, startRow + (endRow - startRow) / 2, startCol + (endCol - startCol) / 2);
		divide(startRow, startCol + (endCol - startCol) / 2 + 1, startRow + (endRow - startRow) / 2, endCol);
		divide(startRow + (endRow - startRow) / 2 + 1, startCol, endRow, startCol + (endCol - startCol) / 2);
		divide(startRow + (endRow - startRow) / 2 + 1, startCol + (endCol - startCol) / 2 + 1, endRow, endCol);
	}
	else {
		if (v[startRow][startCol] == 0) {
			//cout << "흰 종이" << endl;
			white++;
		}
		else {
			//cout << "파란 종이" << endl;
			blue++;
		}
	}
}

int main() {
	cin.tie(NULL);
	ios_base::sync_with_stdio(false);
	int n;
	cin >> n;
	v = vector<vector<int>>(n, vector<int>(n));
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			cin >> v[i][j];
		}
	}
	divide(0, 0, n - 1, n - 1);
	cout << white << endl;
	cout << blue << endl;
	return 0;
}
728x90

'알고리즘 문제' 카테고리의 다른 글

[백준] 4949번 균형잡힌 세상  (0) 2020.04.08
[백준] 2589번 보물섬  (0) 2020.04.07
[백준] 5086번 배수와 약수  (0) 2020.03.30
[백준] 10996번 별 찍기 - 21  (0) 2020.03.30
[백준] 10039번 평균 점수  (0) 2020.03.29

+ Recent posts