문제

수행해야 할 작업 N개 (3 ≤ N ≤ 10000)가 있다. 각각의 작업마다 걸리는 시간(1 ≤ 시간 ≤ 100)이 정수로 주어진다.

 

몇몇 작업들 사이에는 선행 관계라는 게 있어서, 어떤 작업을 수행하기 위해 반드시 먼저 완료되어야 할 작업들이 있다. 이 작업들은 번호가 아주 예쁘게 매겨져 있어서, K번 작업에 대해 선행 관계에 있는(즉, K번 작업을 시작하기 전에 반드시 먼저 완료되어야 하는) 작업들의 번호는 모두 1 이상 (K-1) 이하이다. 작업들 중에는, 그것에 대해 선행 관계에 있는 작업이 하나도 없는 작업이 반드시 하나 이상 존재한다. (1번 작업이 항상 그러하다)

 

모든 작업을 완료하기 위해 필요한 최소 시간을 구하여라. 물론, 서로 선행 관계가 없는 작업들은 동시에 수행 가능하다.

 

 

 

입력

 

첫째 줄에 N이 주어진다.

두 번째 줄부터 N+1번째 줄까지 N개의 줄이 주어진다. 2번째 줄은 1번 작업, 3번째 줄은 2번 작업, ..., N+1번째 줄은 N번 작업을 각각 나타낸다. 각 줄의 처음에는, 해당 작업에 걸리는 시간이 먼저 주어지고, 그 다음에 그 작업에 대해 선행 관계에 있는 작업들의 개수(0 ≤ 개수 ≤ 100)가 주어진다. 그리고 선행 관계에 있는 작업들의 번호가 주어진다.

 

 

 

출력

 

첫째 줄에 모든 작업을 완료하기 위한 최소 시간을 출력한다.

 

 


 

 

문제 해결

 

문제에서 K번 작업의 선행 작업들의 번호는 모두 1이상 K-1 이하라는 조건이 주어졌으므로 dynamic programming 기법을 사용할 수 있습니다. 해결 알고리즘은 간단합니다. K번 작업의 선행 작업들 중 가장 마지막까지 수행된 작업의 시간에 K번의 작업시간을 더해줍니다.

 

 

각 작업이 걸리는 시간을 저장하는 배열을 arr_time[],

dp[i]에 i번 작업이 완료되는 데 걸리는 최소 시간,

task[i][]에 i번 작업의 선행 작업

을 저장하겠습니다.

 

 

한 가지 주의사항이 있습니다. 문제를 잘 읽어보면 선행 작업이 없는 작업은 최소 한 개 이상이며 1번이 그러하다고 적혀있습니다. r을 i번의 선행 작업 번호라고 한다면, dp[i] = max(dp[i], dp[r] + arr_time[i]) 처럼 작성하면 선행 작업이 없는 작업일 때는 이 명령을 수행하지 않으므로 엉뚱한 결과가 나올 수 있습니다. 

 

 

다음과 같은 입력이 주어졌다고 가정하겠습니다.

5

5 0

3 1 1

3 1 2

3 1 3

100 0

 

위 상황은 5개의 작업 중 1번부터 4번까지는 (1 - 2 - 3 - 4)로 연쇄적이고, 5번은 독립적입니다.

 

 

dp[i] = max(dp[i], dp[r] + arr_time[i])로 수행한 결과는 잘못된 값인 14가 나옵니다. 이유는 마지막 입력인 5번 작업은 선행 작업이 없으므로 max 문장이 수행되지 않기 때문입니다. 옳은 결과인 100을 출력하려면 선행 작업이 없는 경우를 대비하여, 선행 작업의 시간이 0 또한 가능하게 만들어줍니다.

 

 

 

코드

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

int n, m, ans, arr_time[10001], dp[10001];
vector<int> task[10001];

int main() {
	cin >> n;

	for (int i = 1; i <= n; i++) {
		cin >> arr_time[i] >> m;

		while (m--) {
			int pretask;
			cin >> pretask;
			task[i].push_back(pretask);
		}
	}

	dp[1] = arr_time[1];

	for (int i = 2; i <= n; i++) {
		int max_pretask = 0;

		for (auto r : task[i])
			max_pretask = max(max_pretask, dp[r]);

		dp[i] = max_pretask + arr_time[i];

		ans = max(ans, dp[i]);
	}

	cout << ans;
}

'🎲 BOJ > 🥈' 카테고리의 다른 글

[C++] 백준 2477 : 참외밭  (0) 2023.02.04
[C++] 백준 10826 : 피보나치 수 4  (0) 2022.02.06
[C++] 백준 1181 : 단어 정렬  (0) 2022.02.04
[C++] 백준 9084 : 동전  (0) 2022.02.03

 

 

 

문제

영선이는 매우 기쁘기 때문에, 효빈이에게 스마일 이모티콘을 S개 보내려고 한다.

 

영선이는 이미 화면에 이모티콘 1개를 입력했다. 이제, 다음과 같은 3가지 연산만 사용해서 이모티콘을 S개 만들어 보려고 한다.

 

  1. 화면에 있는 이모티콘을 모두 복사해서 클립보드에 저장한다.
  2. 클립보드에 있는 모든 이모티콘을 화면에 붙여넣기 한다.
  3. 화면에 있는 이모티콘 중 하나를 삭제한다.

 

모든 연산은 1초가 걸린다. 또, 클립보드에 이모티콘을 복사하면 이전에 클립보드에 있던 내용은 덮어쓰기가 된다. 클립보드가 비어있는 상태에는 붙여넣기를 할 수 없으며, 일부만 클립보드에 복사할 수는 없다. 또한, 클립보드에 있는 이모티콘 중 일부를 삭제할 수 없다. 화면에 이모티콘을 붙여넣기 하면, 클립보드에 있는 이모티콘의 개수가 화면에 추가된다.

 

영선이가 S개의 이모티콘을 화면에 만드는데 걸리는 시간의 최솟값을 구하는 프로그램을 작성하시오.

 

 

입력

첫째 줄에 S (2 ≤ S ≤ 1000) 가 주어진다.

 

 

출력

첫째 줄에 이모티콘을 S개 만들기 위해 필요한 시간의 최솟값을 출력한다.

 

 


 

 

문제 해결

문제에서 주어진 각 연산에서 필요로 하는 조건 설정에 유의해야 한다.

 

 

1. 화면에 있는 이모티콘을 모두 복사해서 클립보드에 저장한다.

 

→ 화면에 출력된 이모티콘의 개수가 1개 이상이어야 한다.

 

 

2. 클립보드에 있는 모든 이모티콘을 화면에 붙여넣기 한다.

 

→ 클립보드에 저장된 이모티콘의 개수가 1개 이상이어야 한다.

 

 

3. 화면에 있는 이모티콘 중 하나를 삭제한다.

 

→ 화면에 출력된 이모티콘의 개수가 1개 이상이어야 한다.

 

 

 

실행시간 단축을 위해 bool형 2차원 배열 visit을 선언하여 관리한다. visit[i][j]에는 현재 화면에 보여지는 이모티콘의 개수가 i개, 클립보드에 저장된 이모티콘의 개수가 j개일 때 해당 상황을 방문한 적이 있는지 저장한다.

 

 

 

 

코드

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

#define MAX 2000
queue<pair<int, int>> q;
queue<int> c;
int s;
bool visit[MAX][MAX];

int bfs() {
	visit[1][0] = 1;
	q.push({ 1,0 });
	c.push(0);

	while (!q.empty()) {
		int disp = q.front().first, clip = q.front().second;
		int cnt = c.front();
		q.pop(); c.pop();

		if (disp == s) return cnt;

		if (disp > 0 && disp <MAX) {

			// 1. 화면에 있는 이모티콘을 모두 클립보드로 복사하는 연산
			if (!visit[disp][disp]) {
				visit[disp][disp] = 1;
				q.push({ disp, disp });
				c.push(cnt + 1);
			}

			// 3. 화면에 있는 이모티콘 중 하나를 삭제하는 연산
			if (!visit[disp - 1][clip]) {
				visit[disp - 1][clip] = 1;
				q.push({ disp - 1, clip });
				c.push(cnt + 1);
			}
		}

		// 2. 클립보드에 있는 모든 이모티콘을 화면에 붙여넣는 연산
		if (clip && disp + clip < MAX) {
			if (!visit[disp + clip][clip]) {
				visit[disp + clip][clip] = 1;
				q.push({ disp + clip,clip });
				c.push(cnt + 1);
			}
		}
	}

	return 0;
}

int main() {
	cin >> s;

	cout << bfs();
}

 

'🎲 BOJ > 🥇' 카테고리의 다른 글

[C++] 백준 1072 : 게임  (0) 2022.02.08
[C++] 백준 2533 : 사회망 서비스(SNS)  (0) 2022.02.07
[C++] 백준 2206 : 벽 부수고 이동하기  (0) 2022.01.30
[C++] 백준 7579 : 앱  (0) 2022.01.30

 

 

 

문제

Day Of Mourning의 기타리스트 강토는 다가오는 공연에서 연주할 N개의 곡을 연주하고 있다. 지금까지 공연과는 다른 공연을 보여주기 위해서 이번 공연에서는 매번 곡이 시작하기 전에 볼륨을 바꾸고 연주하려고 한다.

먼저, 공연이 시작하기 전에 각각의 곡이 시작하기 전에 바꿀 수 있는 볼륨의 리스트를 만들었다. 이 리스트를 V라고 했을 때, V[i]는 i번째 곡을 연주하기 전에 바꿀 수 있는 볼륨을 의미한다. 항상 리스트에 적힌 차이로만 볼륨을 바꿀 수 있다. 즉, 현재 볼륨이 P이고 지금 i번째 곡을 연주하기 전이라면, i번 곡은 P+V[i]나 P-V[i] 로 연주해야 한다. 하지만, 0보다 작은 값으로 볼륨을 바꾸거나, M보다 큰 값으로 볼륨을 바꿀 수 없다.

 

곡의 개수 N과 시작 볼륨 S, 그리고 M이 주어졌을 때, 마지막 곡을 연주할 수 있는 볼륨 중 최댓값을 구하는 프로그램을 작성하시오. 모든 곡은 리스트에 적힌 순서대로 연주해야 한다.

 

 

입력

첫째 줄에 N, S, M이 주어진다. (1 ≤ N ≤ 50, 1 ≤ M ≤ 1,000, 0 ≤ S ≤ M) 둘째 줄에는 각 곡이 시작하기 전에 줄 수 있는 볼륨의 차이가 주어진다. 이 값은 1보다 크거나 같고, M보다 작거나 같다.

 

 

출력

첫째 줄에 가능한 마지막 곡의 볼륨 중 최댓값을 출력한다. 만약 마지막 곡을 연주할 수 없다면 (중간에 볼륨 조절을 할 수 없다면) -1을 출력한다.

 

 


 

 

문제 해결

문제에서 한 가지 조건에 주의해야 한다. 구하는 값은, 모든 곡 중 최대 볼륨이 아니라 마지막 곡의 최대 볼륨이다.

 

dp[i][j]가 1이면 i번의 곡까지 재생할 때 가능한 볼륨 j를 의미한다.

 

1 ≤ N ≤ 50, 1 ≤ M ≤ 1000 이므로 dp[51][1001]로 선언한다.

 

시작 볼륨 S를 dp[0][S] = 1로 설정하기 위해 곡의 인덱스를 1부터 시작한다.

 

 

 

코드

#include <iostream>
using namespace std;

int chk, res, N, S, M, a[52];
bool dp[51][1001];

int main() {
	cin >> N >> S >> M;

	for (int i = 1; i <= N; i++) cin >> a[i];
	
	dp[0][S] = 1;

	for (int i = 0; i < N; i++)
		for (int j = 0; j <= M; j++)
			if (dp[i][j]) {
				if (j + a[i + 1] <= M) dp[i + 1][j + a[i + 1]] = 1;
				if (j - a[i + 1] >= 0) dp[i + 1][j - a[i + 1]] = 1;
			}
	
	chk = -1;

	for (int i = M; i >= 0; i--)
		if (dp[N][i]) {
			chk = i;
			break;
		}

	cout << chk;
}

'🎲 BOJ > 🥈' 카테고리의 다른 글

[C++] 백준 1181 : 단어 정렬  (0) 2022.02.04
[C++] 백준 9084 : 동전  (0) 2022.02.03
[C++] 백준 1991 : 트리 순회  (0) 2022.01.30
[C++] 백준 2631 : 줄 세우기  (0) 2022.01.30

 

 

 

문제

우리는 스마트폰을 사용하면서 여러 가지 앱(App)을 실행하게 된다. 대개의 경우 화면에 보이는 ‘실행 중’인 앱은 하나뿐이지만 보이지 않는 상태로 많은 앱이 '활성화'되어 있다. 앱들이 활성화 되어 있다는 것은 화면에 보이지 않더라도 메인 메모리에 직전의 상태가 기록되어 있는 것을 말한다. 현재 실행 중이 아니더라도 이렇게 메모리에 남겨두는 이유는 사용자가 이전에 실행하던 앱을 다시 불러올 때에 직전의 상태를 메인 메모리로부터 읽어 들여 실행 준비를 빠르게 마치기 위해서이다.

 

하지만 스마트폰의 메모리는 제한적이기 때문에 한번이라도 실행했던 모든 앱을 활성화된 채로 메인 메모리에 남겨두다 보면 메모리 부족 상태가 오기 쉽다. 새로운 앱을 실행시키기 위해 필요한 메모리가 부족해지면 스마트폰의 운영체제는 활성화 되어 있는 앱들 중 몇 개를 선택하여 메모리로부터 삭제하는 수밖에 없다. 이러한 과정을 앱의 ‘비활성화’라고 한다.

 

메모리 부족 상황에서 활성화 되어 있는 앱들을 무작위로 필요한 메모리만큼 비활성화 하는 것은 좋은 방법이 아니다. 비활성화된 앱들을 재실행할 경우 그만큼 시간이 더 필요하기 때문이다. 여러분은 이러한 앱의 비활성화 문제를 스마트하게 해결하기 위한 프로그램을 작성해야 한다

 

현재 N개의 앱, A1, ..., AN이 활성화 되어 있다고 가정하자. 이들 앱 Ai는 각각 mi 바이트만큼의 메모리를 사용하고 있다. 또한, 앱 Ai를 비활성화한 후에 다시 실행하고자 할 경우, 추가적으로 들어가는 비용(시간 등)을 수치화 한 것을 ci 라고 하자. 이러한 상황에서 사용자가 새로운 앱 B를 실행하고자 하여, 추가로 M 바이트의 메모리가 필요하다고 하자. 즉, 현재 활성화 되어 있는 앱 A1, ..., AN 중에서 몇 개를 비활성화 하여 M 바이트 이상의 메모리를 추가로 확보해야 하는 것이다. 여러분은 그 중에서 비활성화 했을 경우의 비용 ci의 합을 최소화하여 필요한 메모리 M 바이트를 확보하는 방법을 찾아야 한다.

 

 

입력

입력은 3줄로 이루어져 있다. 첫 줄에는 정수 N과 M이 공백문자로 구분되어 주어지며, 둘째 줄과 셋째 줄에는 각각 N개의 정수가 공백문자로 구분되어 주어진다.

둘째 줄의 N개의 정수는 현재 활성화 되어 있는 앱 A1, ..., AN이 사용 중인 메모리의 바이트 수인 m1, ..., mN을 의미하며, 셋째 줄의 정수는 각 앱을 비활성화 했을 경우의 비용 c1, ..., cN을 의미한다

 

단, 1 ≤ N ≤ 100, 1 ≤ M ≤ 10,000,000이며, 1 ≤ m1, ..., mN ≤ 10,000,000을 만족한다. 또한, 0 ≤ c1, ..., cN ≤ 100이고, M ≤ m1 + m2 + ... + mN이다.

 

 

출력

필요한 메모리 M 바이트를 확보하기 위한 앱 비활성화의 최소의 비용을 계산하여 한 줄에 출력해야 한다. 

 

 


 

 

문제 해결

dp와 메모이제이션 기법을 이용하여 풀 수 있는 문제다.

 

이 문제의 알고리즘은 "백준 12865 : 평범한 배낭"  비슷하다. 백준의 12865 평범한 배낭에서 dp[i][j]는 i번까지의 물건 중, 담은 무게 j에 올 수 있는 최대 가치 합을 나타냈다.

 

이 문제에서 최대 N은 100, 최대 M은 10,000,000이나 되므로 dp[101][10,000,001]의 배열을 생성할 수 없다.

 

그러나 각 앱을 비활성화하기 위한 비용은 최대 100까지밖에 들지 않는다. 따라서 최대 100개 앱의 비활성 비용은 아무리 많아도 10,000 이하라는 것을 알 수 있다.

 

dp[i][j]의 의미를 바꾸어 i번까지의 앱 중, 비활성 비용 j만큼 사용하여 가능한 최대 메모리로 정의하겠다. 그렇다면 dp[101][10,001]의 크기만큼만 할당하여 관리할 수 있다.

 

 

(+ 전에 배낭 문제를 풀어봤는데도 문제 푸는데 생각보다 오래 걸렸다. 한 번 풀었다고 넘어가지 말고 문제 스크랩해가면서 여러 번 다시 봐야겠다.)

 

 

 

코드

#include <iostream>
using namespace std;

int N, M, m[101], c[101], dp[101][10001];

int main() {
	cin >> N >> M;

	for (int i = 1; i <= N; i++) scanf("%d", m + i);
	for (int i = 1; i <= N; i++) scanf("%d", c + i);

	for (int i = 1; i <= N; i++) {
		for (int j = 1; j <= 10000; j++) {
			if (j < c[i])
            	dp[i][j] = dp[i - 1][j];
			else
				dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - c[i]] + m[i]);
		}
	}

	int t = 1;
	for (; t <= 10000; t++) if (dp[N][t] >= M) break;

	cout << t;
}

'🎲 BOJ > 🥇' 카테고리의 다른 글

[C++] 백준 14226 : 이모티콘  (1) 2022.02.02
[C++] 백준 2206 : 벽 부수고 이동하기  (0) 2022.01.30
[C++] 백준 2098 : 외판원 순회  (0) 2022.01.30
[C++] 백준 5557 : 1학년  (0) 2022.01.30

 

 

 

문제

상근이가 1학년 때, 덧셈, 뺄셈을 매우 좋아했다. 상근이는 숫자가 줄 지어있는 것을 보기만 하면, 마지막 두 숫자 사이에 '='을 넣고, 나머지 숫자 사이에는 '+' 또는 '-'를 넣어 등식을 만들며 놀고 있다. 예를 들어, "8 3 2 4 8 7 2 4 0 8 8"에서 등식 "8+3-2-4+8-7-2-4-0+8=8"을 만들 수 있다.

 

상근이는 올바른 등식을 만들려고 한다. 상근이는 아직 학교에서 음수를 배우지 않았고, 20을 넘는 수는 모른다. 따라서, 왼쪽부터 계산할 때, 중간에 나오는 수가 모두 0 이상 20 이하이어야 한다. 예를 들어, "8+3+2-4-8-7+2+4+0+8=8"은 올바른 등식이지만, 8+3+2-4-8-7이 음수이기 때문에, 상근이가 만들 수 없는 등식이다.

숫자가 주어졌을 때, 상근이가 만들 수 있는 올바른 등식의 수를 구하는 프로그램을 작성하시오.

 

 

입력

첫째 줄에 숫자의 개수 N이 주어진다. (3 ≤ N ≤ 100) 둘째 줄에는 0 이상 9 이하의 정수 N개가 공백으로 구분해 주어진다.

 

 

출력

첫째 줄에 상근이가 만들 수 있는 올바른 등식의 개수를 출력한다. 이 값은 263-1 이하이다.

 

 


 

 

문제 해결

다이나믹 프로그래밍 기법을 사용하여 풀 수 있는 문제다.

문제 풀이의 알고리즘을 떠올리는게 쉽진 않았지만 떠올리기만 한다면 코드 구현은 매우 쉽다.

해결 방법 :

 

배열 dp[N][K]는 N번째 항까지 계산이 완료된 식의 결과값을 K라고 할 때, 가능한 등식의 개수를 의미한다.

초기값 dp[1][a[1]]을 1로 설정해야 한다. 첫 번째 항에서 가능한 등식의 개수는 1개 뿐이기 때문이다.

입력의 마지막 항은 계산하지 않는 등호의 우변이므로 K가 입력의 마지막 항이 되고, 계산은 N-1번째까지 하면 된다.

입력을 a[]배열에 저장하고 a[1]부터 a[n]까지 n개의 입력이 주어진다고 가정하자.

n-1번째까지 계산한 결과값이 마지막 항(a[n])이 되는 등식의 개수 구해야하므로,

최종적으로 구하고자 하는 값은 dp[n-1][a[n]]이 된다.

 

 

 

코드

#include <iostream>
using namespace std;

int n, a[101];
long long dp[101][21];

int main() {
    cin >> n;

    for (int i = 1; i <= n; i++)  // a[1]부터 시작
        cin >> a[i];

    dp[1][a[1]] = 1;

    for (int i = 2; i < n; i++)
        for (int j = 0; j <= 20; j++)
            if (dp[i - 1][j]) { // 이전 항 계산 결과의 0 ~ 20 중에 계산된 적이 있는 숫자가 있을 때

                if (j + a[i] <=20) // i 번째 항과의 덧셈이 20 이하인 경우
                    dp[i][j + a[i]] += dp[i - 1][j];

                if (j - a[i] >= 0) // i 번째 항과의 뺄셈이 0 이상인 경우
                    dp[i][j - a[i]] += dp[i - 1][j];
            }

    cout << dp[n - 1][a[n]];
}

'🎲 BOJ > 🥇' 카테고리의 다른 글

[C++] 백준 7579 : 앱  (0) 2022.01.30
[C++] 백준 2098 : 외판원 순회  (0) 2022.01.30
[C++] 백준 1967 : 트리의 지름  (0) 2022.01.30
[C++] 백준 1197 : 최소 스패닝 트리  (0) 2022.01.30

 

 

 

문제

KOI 어린이집에는 N명의 아이들이 있다. 오늘은 소풍을 가는 날이다. 선생님은 1번부터 N번까지 번호가 적혀있는 번호표를 아이들의 가슴에 붙여주었다. 선생님은 아이들을 효과적으로 보호하기 위해 목적지까지 번호순서대로 일렬로 서서 걸어가도록 하였다. 이동 도중에 보니 아이들의 번호순서가 바뀌었다. 그래서 선생님은 다시 번호 순서대로 줄을 세우기 위해서 아이들의 위치를 옮기려고 한다. 그리고 아이들이 혼란스러워하지 않도록 하기 위해 위치를 옮기는 아이들의 수를 최소로 하려고 한다.

 

예를 들어, 7명의 아이들이 다음과 같은 순서대로 줄을 서 있다고 하자.

3 7 5 2 6 1 4

 

아이들을 순서대로 줄을 세우기 위해, 먼저 4번 아이를 7번 아이의 뒤로 옮겨보자. 그러면 다음과 같은 순서가 된다.

3 7 4 5 2 6 1

 

이제, 7번 아이를 맨 뒤로 옮긴다.

3 4 5 2 6 1 7

 

다음 1번 아이를 맨 앞으로 옮긴다.

1 3 4 5 2 6 7

 

마지막으로 2번 아이를 1번 아이의 뒤로 옮기면 번호 순서대로 배치된다.

1 2 3 4 5 6 7

 

위의 방법으로 모두 4명의 아이를 옮겨 번호 순서대로 줄을 세운다. 위의 예에서 3명의 아이만을 옮겨서는 순서대로 배치할 수가 없다. 따라서, 4명을 옮기는 것이 가장 적은 수의 아이를 옮기는 것이다.

 

N명의 아이들이 임의의 순서로 줄을 서 있을 때, 번호 순서대로 배치하기 위해 옮겨지는 아이의 최소 수를 구하는 프로그램을 작성하시오.

 

 

입력

첫째 줄에는 아이들의 수 N이 주어진다. 둘째 줄부터는 1부터 N까지의 숫자가 한 줄에 하나씩 주어진다. N은 2 이상 200 이하의 정수이다.

 

 

 

출력

첫째 줄에는 번호 순서대로 줄을 세우는데 옮겨지는 아이들의 최소 수를 출력한다.

 

 


 

 

문제 해결

LIS(Longest Incresing Subsequence, 최장 증가 부분 수열)을 이용한 문제다.

문제의 알고리즘은 다음과 같다.

1부터 N까지 오름차순으로 세우되 가장 적게 이동하여야 한다. 따라서 이미 오름차순으로 정렬되어있는 부분 수열들 중, 가장 긴 것을 선택하여 그 길이를 N에서 빼면 문제에서 원하는 값이 나온다.

주의사항 : 나올 수 있는 최소 부분 수열의 길이는 1이므로 dp[0]에 0을 대입하고 dp[1]부터 시작하여야 한다.

예를 들어 입력이 5 4 3 2 1인 경우, dp[1]부터 dp[5]까지는 모두 1의 값을 갖는다.

이는 각 인덱스가 dp[1]이 아닌 dp[0](항상 0)부터 비교해야 나올 수 있다.

 

 

 

코드

#include <iostream>
using namespace std;

int n, m, a[202], dp[202];

int main() {
    cin >> n;

    for (int i = 1; i <= n; i++)
        cin >> a[i];

    for (int i = 1; i <= n; i++)
        for (int j = 0; j < i; j++)
            if (a[i] > a[j])
                dp[i] = max(dp[i], dp[j] + 1);

    for (int i = 1; i <= n; i++) m = max(m, dp[i]);

    cout << n - m;
}

'🎲 BOJ > 🥈' 카테고리의 다른 글

[C++] 백준 9084 : 동전  (0) 2022.02.03
[C++] 백준 1495 : 기타리스트  (0) 2022.02.01
[C++] 백준 1991 : 트리 순회  (0) 2022.01.30
[C++] 백준 1406 : 에디터  (2) 2022.01.29

+ Recent posts