※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 3277번 문제인 DOMAINS이다.
문제는 아래 링크를 확인하자.

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

 

3277번: DOMAINS

The first line of input file contains a natural number N, 1 ≤ N ≤ 100, the number of addresses. Each of the following N lines contains one simplified address. A simplified address may begin with a prefix 'http://', after which comes one or more words s

www.acmicpc.net

주어지는 주소에서 문제에서 요구하는 문자열을 파싱해 가장 많이 등장한 문자열을 찾는 문제이다.

 

글쓴이는 다음과 같은 순서로 주소에서 필요한 부분을 파싱했다.

 

(1) 주어진 주소의 앞에 "https://"가 앞에 존재한다면 제거, 주소의 맨 뒤에 '/' 추가

(2) 앞에서부터 읽어나가며 '/'을 발견하기 전 '.'을 발견한다면 문자열의 맨 앞부터 해당 '.'까지를 제거

(3) '/'을 발견하면 문자열의 맨 앞부터 '/' 전까지가 파싱하려는 문자열이 된다.

 

주어지는 문자열을 multiset 자료구조로 관리하면 각 문자열이 몇번씩 등장했는지를 쉽게 알아낼 수 있다. 또한 중복없는 출력을 위해 set 자료구조를 이용해 편하게 구현할 수 있다.

 

아래는 제출한 소스코드이다.

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

int N;
multiset<string> st;

int cnt;
set<string> ans;

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);

	cin >> N;
	while (N--) {
		string s; cin >> s; s += '/';
		if (s.length() > 6 && s.substr(0, 7) == "http://") s.erase(s.begin(), s.begin() + 7);

		while (1) {
			int idx = 0;
			while (s[idx] != '.' && s[idx] != '/') idx++;
			if (s[idx] == '.') s.erase(s.begin(), s.begin() + idx + 1);
			else {
				st.insert(s.substr(0, idx));
				break;
			}
		}
	}

	for (auto& x : st) {
		if (st.count(x) > cnt) {
			cnt = st.count(x);
			ans.clear();
			ans.insert(x);
		}
		else if (st.count(x) == cnt) ans.insert(x);
	}

	cout << cnt << '\n';
	for (auto& x : ans) cout << x << ' ';
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 3285 // C++] DECODE  (0) 2023.08.31
[BOJ 3278 // C++] EXCHANGE  (0) 2023.08.30
[BOJ 2082 // C++] 시계  (0) 2023.08.28
[BOJ 2079 // C++] 팰린드롬  (1) 2023.08.27
[BOJ 3279 // C++] DOLLARS  (0) 2023.08.26

※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 2082번 문제인 시계이다.
문제는 아래 링크를 확인하자.

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

 

2082번: 시계

코레스코 콘도의 각 방에는 디지털 시계가 설치되어 있다. 디지털 시계에는 4개의 숫자가 표현될 수 있으며, 이것은 'hh:mm'의 형식으로 시간을 표현한다. 즉, 앞의 두 자리는 시간을, 뒤의 두 자리

www.acmicpc.net

시계가 표기하는 문자 X가 의미할 수 있는 가장 작은 숫자 i는 "i를 정상적으로 나타낼 때 켜져있을 수 없는(i를 정상적으로 나타낼 때 꺼져있어야 하는) 다이오드가 X에 켜져있지 않은, 가장 작은 i"와 같다. 이와 같은 관찰을 이용해 각 문자가 나타낼 수 있는 가장 작은 숫자를 찾아 문제를 해결하자.

 

위와 같이 찾은 숫자들이 올바른 시각을 구성하지 못한다면 주어진 입력은 올바른 시각을 표기할 수 없다는 것을 의미함을 관찰하자. (위에서 구한 수가 가능한 가장 작은 수이기 때문이다.) 따라서 위와 같은 풀이로 문제의 답을 항상 구해낼 수 있음을 보장할 수 있다.

 

아래는 제출한 소스코드이다.

#include <iostream>
using namespace std;

string num[10][5] =
{
	{
		"###",
		"#.#",
		"#.#",
		"#.#",
		"###"
	},
	{
		"..#",
		"..#",
		"..#",
		"..#",
		"..#"
	},
	{
		"###",
		"..#",
		"###",
		"#..",
		"###"
	},
	{
		"###",
		"..#",
		"###",
		"..#",
		"###"
	},
	{
		"#.#",
		"#.#",
		"###",
		"..#",
		"..#"
	},
	{
		"###",
		"#..",
		"###",
		"..#",
		"###"
	},
	{
		"###",
		"#..",
		"###",
		"#.#",
		"###"
	},
	{
		"###",
		"..#",
		"..#",
		"..#",
		"..#"
	},
	{
		"###",
		"#.#",
		"###",
		"#.#",
		"###"
	},
	{
		"###",
		"#.#",
		"###",
		"..#",
		"###"
	}
};

string digit[4][5];
int ans[4];

bool func(int i, int dgt) {
	for (int r = 0; r < 5; r++) {
		for (int c = 0; c < 3; c++) {
			if (num[dgt][r][c] == '.' && digit[i][r][c] == '#') return 0;
		}
	}
	return 1;
}

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);

	for (int r = 0; r < 5; r++) {
		for (int i = 0; i < 4; i++) cin >> digit[i][r];
	}

	for (int i = 0; i < 4; i++) {
		int dgt = 0;
		while (!func(i, dgt)) dgt++;

		ans[i] = dgt;
	}

	cout << ans[0] << ans[1] << ':' << ans[2] << ans[3];
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 3278 // C++] EXCHANGE  (0) 2023.08.30
[BOJ 3277 // C++] DOMAINS  (0) 2023.08.29
[BOJ 2079 // C++] 팰린드롬  (1) 2023.08.27
[BOJ 3279 // C++] DOLLARS  (0) 2023.08.26
[BOJ 3284 // C++] MASS  (0) 2023.08.25

※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 2079번 문제인 팰린드롬이다.
문제는 아래 링크를 확인하자.

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

 

2079번: 팰린드롬

첫째 줄에 단어가 입력으로 들어온다. 단어는 영어 소문자로만 이루어져 있으며, 그 길이는 2,000을 넘지 않는다.

www.acmicpc.net

모든 팰린드롬 문자열은 그 길이가 3 이상이라면 양 끝의 두 문자를 지워도 다시 팰린드롬 문자열이 됨을 상기하자.

 

따라서, 가운데를 담당할 문자 하나 또는 둘을 먼저 고르고 양 옆에 문자를 하나씩 이어나가 팰린드롬 성질이 깨질 때까지 살피는 것으로 주어진 문자열에 존재하는 모든 팰린드롬 문자열에 한번씩 접근할 수 있게 된다.

 

dp[j]를 주어진 문자열의 [0,j] 구간에 해당하는 부분문자열에 대하여 이를 최소 개수의 팰린드롬으로 분할할 때의 개수라 하면 이는 [i,j] 구간에 해당하는 부분무자열이 팰린드롬인 모든 i에 대하여 dp[i - 1] + 1의 최솟값으로 계산할 수 있음을 관찰하자.

 

위의 관계를 인덱스를 노드, [i,j] 구간을 i에서 j+1로 향하는 에지로 하는 그래프로 모델링하자. 이 때 주어진 문제는 0번 인덱스에서 (문자열의 길이)번 인덱스까지 향하는 최단거리 문제로 바꾸어 생각할 수 있게 된다. BFS 등을 이용해 해당하는 최단거리를 구하고 문제를 해결하자.

 

아래는 제출한 소스코드이다.

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

string s; int slen;
vector<int> G[2001];
int dist[2001];

void bfs() {
	queue<int> que;
	que.push(0);

	while (!que.empty()) {
		int cur = que.front(); que.pop();
		for (auto& nxt : G[cur]) {
			if (dist[nxt]) continue;
			dist[nxt] = dist[cur] + 1;
			que.push(nxt);
		}
	}
}

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);

	cin >> s; slen = s.length();
	for (int mid = 0; mid < slen; mid++) { // 홀수길이 팰린드롬
		int L = mid, R = mid;
		while (-1 < L && R < slen && s[L] == s[R]) {
			G[L].emplace_back(R + 1);
			L--, R++;
		}
	}
	for (int midL = 0, midR = 1; midR < slen; midL++, midR++) { // 짝수길이 팰린드롬
		int L = midL, R = midR;
		while (-1 < L && R < slen && s[L] == s[R]) {
			G[L].emplace_back(R + 1);
			L--, R++;
		}
	}

	bfs();

	cout << dist[slen];
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 3277 // C++] DOMAINS  (0) 2023.08.29
[BOJ 2082 // C++] 시계  (0) 2023.08.28
[BOJ 3279 // C++] DOLLARS  (0) 2023.08.26
[BOJ 3284 // C++] MASS  (0) 2023.08.25
[BOJ 3283 // C++] BARCODE  (0) 2023.08.24

※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 3279번 문제인 DOLLARS이다.
문제는 아래 링크를 확인하자.

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

 

3279번: DOLLARS

Dave somehow acquired exchange rates of US dollar to German marks for several days in the future. Write a program that will suggest Dave when to buy or sell marks or dollars so that, starting with 100 dollars he ends up with the highest possible amount of

www.acmicpc.net

소지한 달러를 A환율로 마르크로 바꾼 뒤 B환율로 다시 달러로 바꾸면 소지한 달러는 A/B배로 증가한다.

 

매 연속한 두 날 사이의 환율을 보며 위와 같은 환전으로 이득을 볼 수 있을 때마다(즉 A/B>1일 때마다) 환전을 반복하는 것으로 문제를 해결하자.

 

아래는 제출한 소스코드이다.

#include <iostream>
using namespace std;
typedef long double ld;

ld ans = 100;
ld prv = 0;

int N;

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);

	cout << fixed;
	cout.precision(2);

	cin >> N;
	while (N--) {
		ld cur; cin >> cur;
		if (prv > cur) ans *= (prv / cur);
		prv = cur;
	}

	cout << ans;
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 2082 // C++] 시계  (0) 2023.08.28
[BOJ 2079 // C++] 팰린드롬  (1) 2023.08.27
[BOJ 3284 // C++] MASS  (0) 2023.08.25
[BOJ 3283 // C++] BARCODE  (0) 2023.08.24
[BOJ 1799 // C++] 비숍  (0) 2023.08.23

※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 3284번 문제인 MASS이다.
문제는 아래 링크를 확인하자.

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

 

3284번: MASS

The first and only line of input file contains a formula of a molecule whose mass needs to be determined. A formula of a molecule will consist of characters H, C, O, (, ) , 2, 3, ..., 9 only. Its length will be less or equal to 100 characters.

www.acmicpc.net

각 괄호가 닫힐 때마다 대응되는 괄호쌍 안에 담긴 물질의 질량을 합쳐 하나의 값으로 바꿔주고, 한자리 수를 입력받을 때마다 바로 직전에 작업한 값에 곱해 해당 한자리 수를 곱해나가며 문제를 해결하자.

 

괄호의 순서를 관리하는 것은 스택 자료구조를 이용하면 편하게 해낼 수 있다.

 

아래는 제출한 소스코드이다.

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

string s;
vector<int> stk;
int ans;

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);

	cin >> s;
	for (auto& l : s) {
		if (l == 'H') stk.emplace_back(1);
		else if (l == 'C') stk.emplace_back(12);
		else if (l == 'O') stk.emplace_back(16);
		else if (l == '(') stk.emplace_back(-1);
		else if (l == ')') {
			int tmp = 0;
			while (stk.back() > -1) {
				tmp += stk.back();
				stk.pop_back();
			}
			stk.pop_back();
			stk.emplace_back(tmp);
		}
		else stk.back() *= l - '0';
	}

	while (!stk.empty()) {
		ans += stk.back();
		stk.pop_back();
	}

	cout << ans;
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 2079 // C++] 팰린드롬  (1) 2023.08.27
[BOJ 3279 // C++] DOLLARS  (0) 2023.08.26
[BOJ 3283 // C++] BARCODE  (0) 2023.08.24
[BOJ 1799 // C++] 비숍  (0) 2023.08.23
[BOJ 2546 // C++] 경제학과 정원영  (0) 2023.08.22

※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 3283번 문제인 BARCODE이다.
문제는 아래 링크를 확인하자.

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

 

3283번: BARCODE

The first and only line of output file should contain a sequence of binary digits represented with bar code given in input file if it can be determined. If a sequence cannot be determined, word ‘UNDETERMINABLE’ should be written to the first line inste

www.acmicpc.net

고려해야 할 케이스가 많은 DP문제이다.

 

먼저 주어진 입력을 잘 처리하여 각 세로줄이 검은 줄('B'로 표기), 하얀 줄('W'로 표기), 모르는 줄('?'로 표기) 중 무엇인지를 구해두자. 이 과정에서 한 세로줄에 'B'와 'W'와 같이 있는 경우가 발견된다면 "UNDETERMINABLE"을 출력해주자.

 

그 뒤, 초기값으로 앞의 두 세로줄이 의미할 수 있는 문자열에 대한 상태를 저장하고, 세번째 세로줄부터 각 세로줄이 해당세로줄을 포함하는 크기 1 또는 2의 문자열로 구간을 나눌 수 있는지의 여부에 따라 DP를 진행해 문제를 해결해주자.

 

아래의 구현에서의 dp배열의 값은 "여러 경우가 존재함"을 의미하는 -1, "경우가 존재하지 않음"을 의미하는 0, "해당 세로줄이 그 한칸으로 기능하는 경우가 가능한 유일한 해석임"을 의미하는 1, "해당 세로줄이 그 전 세로줄과 이어 한칸으로 기능하는 경우가 가능한 유일한 해석임"을 의미하는 2로 구성되어있으니 코드를 읽을 때 참고하자. 여기에서 배열의 값인 1과 2는 dp의 해를 역추적하는 데에도 유용하게 사용할 수 있다. 

 

예외적으로, '?'를 의미하는 세로줄 하나만이 입력이 들어왔을 경우의 답은 "0"임에 유의하자. '?'를 'B'로 해석해도 'W'로 해석해도 해당 문자열은 항상 "0"으로 동일하게 해석되기 때문이다. 이와 같이 복수의 해석이 가능하지만 그 모든 해석이 같은 문자열을 가리키는 경우는 이 경우가 유일하다. (증명은 간단하므로 생략한다.)

 

아래는 제출한 소스코드이다.

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

int N;
string s[5];
bool chk = 1;
char arr[100];
int dp[100][2];
int cnt;

int idx, c;
vector<int> ans;

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);

	cin >> N;
	for (int r = 0; r < 5; r++) cin >> s[r];

	for (int i = 0; i < N; i++) {
		bool black = 0, white = 0;
		for (int r = 0; r < 5; r++) {
			if (s[r][i] == '.') white = 1;
			else if (s[r][i] == 'X') black = 1;
		}
		if (black && white) chk = 0;
		else if (black) arr[i] = 'B';
		else if (white) arr[i] = 'W';
		else arr[i] = '?';
	}

	if (!chk) {
		cout << "UNDETERMINABLE";
		return 0;
	}
	
	if (N == 1) {
		cout << '0';
		return 0;
	}

	if (arr[0] == 'B') dp[0][0] = 1;
	else if (arr[0] == 'W') dp[0][1] = 1;
	else dp[0][0] = dp[0][1] = 1;

	if (arr[0] == 'B' && arr[1] == 'B') dp[1][0] = 2;
	else if (arr[0] == 'B' && arr[1] == 'W') dp[1][1] = 1;
	else if (arr[0] == 'B' && arr[1] == '?') dp[1][0] = 2, dp[1][1] = 1;
	else if (arr[0] == 'W' && arr[1] == 'B') dp[1][0] = 1;
	else if (arr[0] == 'W' && arr[1] == 'W') dp[1][1] = 2;
	else if (arr[0] == 'W' && arr[1] == '?') dp[1][0] = 1, dp[1][1] = 2;
	else if (arr[0] == '?' && arr[1] == 'B') dp[1][0] = -1;
	else if (arr[0] == '?' && arr[1] == 'W') dp[1][1] = -1;
	else dp[1][0] = -1, dp[1][1] = -1;

	for (int i = 2; i < N; i++) {
		if (dp[i - 2][1] && (arr[i - 1] == 'B' || arr[i - 1] == '?') && (arr[i] == 'B' || arr[i] == '?')) {
			if (dp[i - 2][1] < 0 || dp[i][0]) dp[i][0] = -1;
			else dp[i][0] = 2;
		}
		if (dp[i - 2][0] && (arr[i - 1] == 'W' || arr[i - 1] == '?') && (arr[i] == 'W' || arr[i] == '?')) {
			if (dp[i - 2][0] < 0 || dp[i][1]) dp[i][1] = -1;
			else dp[i][1] = 2;
		}
		if (dp[i - 1][1] && (arr[i] == 'B' || arr[i] == '?')) {
			if (dp[i - 1][1] < 0 || dp[i][0]) dp[i][0] = -1;
			else dp[i][0] = 1;
		}
		if (dp[i - 1][0] && (arr[i] == 'W' || arr[i] == '?')) {
			if (dp[i - 1][0] < 0 || dp[i][1]) dp[i][1] = -1;
			else dp[i][1] = 1;
		}
	}
	
	if (dp[N - 1][0] == -1 || dp[N - 1][1] == -1 || (dp[N - 1][0] > 0 && dp[N - 1][1] > 0) || (dp[N - 1][0] == 0 && dp[N - 1][1] == 0)) {
		cout << "UNDETERMINABLE";
		return 0;
	}

	idx = N - 1;
	if (dp[idx][1] > 0) c = 1;

	while (idx > -1) {
		ans.emplace_back(dp[idx][c] - 1);
		idx -= dp[idx][c];
		c ^= 1;
	}

	while (!ans.empty()) {
		cout << ans.back();
		ans.pop_back();
	}
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 3279 // C++] DOLLARS  (0) 2023.08.26
[BOJ 3284 // C++] MASS  (0) 2023.08.25
[BOJ 1799 // C++] 비숍  (0) 2023.08.23
[BOJ 2546 // C++] 경제학과 정원영  (0) 2023.08.22
[BOJ 15822 // C++] Ah-Choo!  (0) 2023.08.22

+ Recent posts