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

 

이번에 볼 문제는 백준 2482번 문제인 색상환이다.
문제는 아래 링크를 확인하자.

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

 

2482번: 색상환

첫째 줄에 N색상환에서 어떤 인접한 두 색도 동시에 선택하지 않고 K개의 색을 고를 수 있는 경우의 수를 1,000,000,003 (10억 3) 으로 나눈 나머지를 출력한다.

www.acmicpc.net

경우의 수를 세는 문제이다.

 

N은 전체 색상의 수, K는 선택하고자 하는 색상의 수이다.

색상환의 한 곳을 잘라 일렬로 나열하고 사용할 색상에 O, 사용하지 않을 색상에 X를 표시한다고 생각하자.

이때, 관찰을 통해 자른 색상환의 맨 마지막 색상이 "X"일 경우의 수는 "OX" 표기 K개와 "X" 표기 N-2K개를 나열하는 경우의 수와 같다는 것을 알 수 있다.

마찬가지로, 자른 색상환의 맨 마지막 색상이 "O"일 경우의 수는 마지막 칸의 색상을 "O", 첫 칸의 색상을 "X"로 고정한 뒤 "OX" 표기 K-1개와 "X" 표기 N-2K개를 나열하는 경우의 수와 같다는 것을 알 수 있다.

 

남은 일은 조합을 이용하여 위의 값을 계산하여 출력하는 것이다. 단, N=1인 경우 1가지 색을 선택할 수 있다는 점과 조합값을 계산할 때의 index가 음수가 되지 않는지 등을 주의하여 구현하자.

 

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

#include <iostream>
using namespace std;

int comb[1001][1001];

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

	for (int i = 0; i <= 1000; i++) {
		comb[i][0] = comb[i][i] = 1;
	}

	for (int i = 2; i <= 1000; i++) {
		for (int j = 1; j < i; j++) {
			comb[i][j] = (comb[i - 1][j - 1] + comb[i - 1][j]) % 1000000003;
		}
	}

	int N, K; cin >> N >> K;
	if (N == 1) cout << 1;
	else if (N == K) cout << 0;
	else cout << (comb[N - K][K] + comb[N - K - 1][K - 1]) % 1000000003;
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 2631 // C++] 줄세우기  (0) 2021.08.22
[BOJ 1695 // C++] 팰린드롬 만들기  (0) 2021.08.21
[BOJ 12970 // C++] AB  (0) 2021.08.19
[BOJ 1956 // C++] 운동  (0) 2021.08.18
[BOJ 1990 // C++] 소수인팰린드롬  (0) 2021.08.17

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

 

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

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

 

12970번: AB

첫째 줄에 문제의 조건을 만족하는 문자열 S를 출력한다. 가능한 S가 여러 가지라면, 아무거나 출력한다. 만약, 그러한 S가 존재하지 않는 경우에는 -1을 출력한다.

www.acmicpc.net

글쓴이는 아래와 같은 전략을 이용하였다.

1) A를 N/2개, B를 N-N/2개 이용할 것이다. AB 개수의 최댓값은 (A의 개수)*(B의 개수)가 된다.

1-1) K가 AB 개수의 최댓값을 넘어간다면 -1을 출력해주자.

 

2) 정수 AA를 K/B, BB를 K%B라 하자.

문자열의 시작에 AA개의 'A'를, 문자열의 끝을 'A' 하나와 'B' BB개를 쓴 뒤 남은 'A'를 채워넣고 시작과 끝 사이에는 남은 'B'를 채워넣으면 K개의 AB가 포함된 문자열을 얻을 수 있다. 시작부분의 A가 포함된 K/B쌍의 AB와 뒤에 따로 있는 A가 포함된 K%B쌍의 AB의 개수를 합하면 K쌍의 AB를 얻을 수 있기 때문이다.

 

이와 같이 구현할 때, K가 가능한 최댓값이 주어진 경우를 보더케이스로 생각해야함에 유의하자. (잔여 A가 남지 않기 때문이다)

 

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

#include <iostream>
using namespace std;

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

	int N, K; cin >> N >> K;
	int A = N / 2; int B = N - A;

	if (K > A * B) cout << -1;
	else if (K == A * B) {
		while (A--) cout << 'A';
		while (B--) cout << 'B';
	}
	else {
		int AA = K / B, BB = K % B;
		int aa = A - AA - 1, bb = B - BB;
		while (AA--) cout << 'A';
		while (bb--) cout << 'B';
		cout << 'A';
		while (BB--) cout << 'B';
		while (aa--) cout << 'A';
	}
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 1695 // C++] 팰린드롬 만들기  (0) 2021.08.21
[BOJ 2482 // C++] 색상환  (0) 2021.08.20
[BOJ 1956 // C++] 운동  (0) 2021.08.18
[BOJ 1990 // C++] 소수인팰린드롬  (0) 2021.08.17
[BOJ 1969 // C++] DNA  (0) 2021.08.16

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

 

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

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

 

1956번: 운동

첫째 줄에 V와 E가 빈칸을 사이에 두고 주어진다. (2 ≤ V ≤ 400, 0 ≤ E ≤ V(V-1)) 다음 E개의 줄에는 각각 세 개의 정수 a, b, c가 주어진다. a번 마을에서 b번 마을로 가는 거리가 c인 도로가 있다는 의

www.acmicpc.net

방향그래프의 각 점에서 자기자신으로 가는 최단거리 사이클을 모두 구하는 문제는 플로이드-워셜(Floyd-Warshall) 알고리즘을 이용하여 간단히 해결할 수 있다.

 

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

#include <iostream>
using namespace std;

int dist[401][401];

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

	int N, E; cin >> N >> E;
	
	for (int i = 1; i <= N; i++) {
		for (int j = 1; j <= N; j++) {
			dist[i][j] = 11111111;
		}
	}

	while (E--) {
		int x, y, w; cin >> x >> y >> w;
		dist[x][y] = w;
	}

	for (int k = 1; k <= N; k++) {
		for (int i = 1; i <= N; i++) {
			for (int j = 1; j <= N; j++) {
				if (dist[i][j] > dist[i][k] + dist[k][j]) {
					dist[i][j] = dist[i][k] + dist[k][j];
				}
			}
		}
	}

	int ans = 11111111;
	for (int k = 1; k <= N; k++) {
		ans = min(ans, dist[k][k]);
	}

	if (ans == 11111111) cout << -1;
	else cout << ans;
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 2482 // C++] 색상환  (0) 2021.08.20
[BOJ 12970 // C++] AB  (0) 2021.08.19
[BOJ 1990 // C++] 소수인팰린드롬  (0) 2021.08.17
[BOJ 1969 // C++] DNA  (0) 2021.08.16
[BOJ 20136 // C++] 멀티탭 스케줄링 2  (0) 2021.08.15

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

 

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

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

 

1990번: 소수인팰린드롬

151은 소수이면서 동시에 팰린드롬이기 때문에 소수인 팰린드롬이다. 팰린드롬이란 앞으로 읽어나 뒤로 읽으나 같은 수를 말한다. 예를 들어 1234는 앞으로 읽으면 1234지만, 뒤로 읽으면 4321이 되

www.acmicpc.net

다음과 같은 관찰을 하자:

1) 짝수자리 팰린드롬 수는 11의 배수이다. 따라서 답의 후보가 될 수 없다.

2) 100000000(1억)은 답이 될 수 없으므로, 이 문제의 답이 될 후보는 최대 7자리의 수일 것이다.

 

위 관찰에 따라 에라토스테네스의 체를 이용하여 1000만 이하의 소수를 모두 구하고, 주어진 두 수 사이의 수를 탐색하면서 팰린드롬인 소수를 모두 출력하는 것으로 문제를 해결할 수 있다.

 

탐색범위가 8자리 이상이 들어오는 경우 1000만 미만으로 조정해주는 것을 잊지 말자.

 

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

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

vector<bool> sieve(10000000);

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

	for (int i = 2; i < 3162; i++) {
		if (sieve[i]) continue;
		for (int j = i * i; j < 10000000; j += i) {
			sieve[j] = 1;
		}
	}

	int L, R; cin >> L >> R;
	R = min(R, 9999999);
	for (int i = L; i <= R; i++) {
		if (sieve[i]) continue;
		string s = to_string(i);
		int l = 0, r = s.length() - 1;
		bool chk = 1;
		while (l < r) {
			if (s[l] != s[r]) chk = 0;
			l++; r--;
		}
		
		if (chk) cout << i << '\n';
	}

	cout << -1;
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 12970 // C++] AB  (0) 2021.08.19
[BOJ 1956 // C++] 운동  (0) 2021.08.18
[BOJ 1969 // C++] DNA  (0) 2021.08.16
[BOJ 20136 // C++] 멀티탭 스케줄링 2  (0) 2021.08.15
[BOJ 1339 // C++] 단어 수학  (0) 2021.08.14

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

 

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

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

 

1969번: DNA

DNA란 어떤 유전물질을 구성하는 분자이다. 이 DNA는 서로 다른 4가지의 뉴클레오티드로 이루어져 있다(Adenine, Thymine, Guanine, Cytosine). 우리는 어떤 DNA의 물질을 표현할 때, 이 DNA를 이루는 뉴클레오

www.acmicpc.net

해밍 거리(Hamming Distance)는 길이가 같은 두 문자열에 대하여 순서대로 각 문자를 대응시킬 때, 서로 다른 문자가 대응된 개수를 의미한다. 이는 가장 간단한 편집거리(Edit Distance) 중 하나이기도 하다.

 

주어지는 문자열들의 각 i번째 문자는 다른 순서의 문자와 대응될 일이 없으므로, 각 순서에 대하여 가장 많이 등장한 문자를 새로 만드는 문자열의 문자로 선택하는 것이 항상 최선임을 알 수 있다. 그러한 문자가 여럿 있을 경우, 사전순으로 가장 빠른 문자열을 만들어야하므로 A, C, G, T 순으로 고르도록 하자.

 

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

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

int cnt[50][4];

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

	int N, M; cin >> N >> M;
	for (int n = 0; n < N; n++) {
		string s; cin >> s;
		for (int i = 0; i < M; i++) {
			if (s[i] == 'A') cnt[i][0]++;
			else if (s[i] == 'C') cnt[i][1]++;
			else if (s[i] == 'G') cnt[i][2]++;
			else cnt[i][3]++;
		}
	}

	int dist = 0;
	for (int i = 0; i < M; i++) {
		int x = (cnt[i][0] >= cnt[i][1]) ? 0 : 1;
		int y = (cnt[i][2] >= cnt[i][3]) ? 2 : 3;
		int idx = (cnt[i][x] >= cnt[i][y]) ? x : y;

		dist += cnt[i][idx];

		if (idx == 0) cout << 'A';
		else if (idx == 1) cout << 'C';
		else if (idx == 2) cout << 'G';
		else cout << 'T';
	}
	cout << '\n' << N * M - dist;
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 1956 // C++] 운동  (0) 2021.08.18
[BOJ 1990 // C++] 소수인팰린드롬  (0) 2021.08.17
[BOJ 20136 // C++] 멀티탭 스케줄링 2  (0) 2021.08.15
[BOJ 1339 // C++] 단어 수학  (0) 2021.08.14
[BOJ 1080 // C++] 행렬  (0) 2021.08.13

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

 

이번에 볼 문제는 백준 20136번 문제인 멀티탭 스케줄링 2이다.
문제는 아래 링크를 확인하자.

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

 

20136번: 멀티탭 스케줄링 2

기숙사에서 살고 있는 준규는 한 개의 멀티탭을 이용하고 있다. 준규는 키보드, 헤어드라이기, 핸드폰 충전기, 디지털 카메라 충전기 등 여러 개의 전기용품을 사용하면서 어쩔 수 없이 각종 전

www.acmicpc.net

Bélády's algorithm(Optimal page replacement algorithm)과 그 구현을 묻는 문제이다.

이 알고리즘에 따르면, 현재 멀티탭에 더 꽂을 공간이 없을 때 빼야 할 물건은 "앞으로 가장 나중에 사용하게 될 물건"이 된다. 앞으로 더 사용하지 않는다면 무한대의 시간 뒤에 사용하게 된다고 생각하자.

 

Bélády's algorithm에 대한 내용은 다음 링크를 참고하자:

https://en.wikipedia.org/wiki/Cache_replacement_policies#B%C3%A9l%C3%A1dy's_algorithm

https://en.wikipedia.org/wiki/Page_replacement_algorithm#The_theoretically_optimal_page_replacement_algorithm

 

이러한 알고리즘은 "앞으로 다음에 이 물건을 얼마나 나중에 사용하는가"를 우선순위로 한 우선순위 큐(priority queue)를 이용하여 효율적으로 구현할 수 있다.

 

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

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

struct process {
    int type;
    int next;
};

struct comp {
    bool operator() (process p1, process p2) {
        return p1.next < p2.next;
    }
};

process t[500001];
vector<bool> visited(500001);
int arr[500001];

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

    int N, K; cin >> N >> K;
    
    for (int i = 1; i <= K; i++) {
        int x; cin >> x;
        t[i].type = x;
        t[i].next = 1000000;
        t[arr[x]].next = i;
        arr[x] = i;
    }

    int cnt = 0, ans = 0;
    priority_queue<process, vector<process>, comp> pq;

    for (int i = 1; i <= K; i++) {
        if (visited[t[i].type]) pq.push(t[i]);
        else if (cnt < N) {
            cnt++;
            visited[t[i].type] = 1;
            pq.push(t[i]);
        }
        else {
            ans++;
            while (!visited[pq.top().type]) pq.pop();
            visited[pq.top().type] = 0; pq.pop();
            visited[t[i].type] = 1;
            pq.push(t[i]);
        }
    }

    cout << ans;
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 1990 // C++] 소수인팰린드롬  (0) 2021.08.17
[BOJ 1969 // C++] DNA  (0) 2021.08.16
[BOJ 1339 // C++] 단어 수학  (0) 2021.08.14
[BOJ 1080 // C++] 행렬  (0) 2021.08.13
[BOJ 15892 // C++] 사탕 줍는 로봇  (0) 2021.08.12

+ Recent posts