본문 바로가기
알고리즘/백준

[백준 5557] 1학년 (C++)

by fortissimo 2024. 6. 21.

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

문제


 

상근이가 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 문제.

각 중간 단계마다 0부터 20까지 만들 수 있는 경우의 수를 2차원 dp 배열에 저장한다. 행은 맨 마지막 숫자가 나오도록 등식의 맨 마지막에 =가 붙어야 하므로 N-1개 필요하고, 열은 0부터 20까지 만들 수 있는 경우의 수를 저장하기 위해 21개 필요하므로 크기는 dp[N-1][21]가 된다.

 

각 단계마다 숫자 j에 이번 단계의 숫자 arr[i]를 더해 l을 만들었다고 하면, l를 만드는 경우의 수는 덧셈의 경우 한가지밖에 없으므로 j를 만드는 경우의 수와 같다. 마찬가지로 j에 arr[i]를 빼서 만든 m의 경우의 수는 빼는 경우 한가지밖에 없으므로 j를 만드는 경우의 수와 같다.

위의 설명을 이용해 반복문을 돌려 dp[i][j + arr[i]]와 dp[i][j-arr[i]]에 각각 dp[i][j]를 더해 경우의 수를 구한다. N-2번째 인덱스까지 반복한 뒤 dp[N-2][arr[N-1]]를 출력해주면 된다.

 

아래는 코드.

더보기
#include <iostream>
#include <utility>
using namespace std;

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

	int N;
	cin >> N;
	int* arr = new int[N];
	long long** nums = new long long*[N];
	for (int i = 0; i < N; i++)
	{
		cin >> arr[i];
		nums[i] = new long long[21];
		for (int j = 0; j < 21; j++)
		{
			nums[i][j] = 0;
		}
	}
	nums[0][arr[0]]= 1;
	for (int i = 1; i < N-1; i++)
	{
		for (int j = 0; j < 21; j++)
		{
			if (j + arr[i] >= 0 && j + arr[i] <= 20)
			{
				nums[i][j + arr[i]] += nums[i - 1][j];
			}
			if (j - arr[i] >= 0 && j - arr[i] <= 20)
			{
				nums[i][j - arr[i]] += nums[i - 1][j];
			}
		}
	}
	for (int i = 0; i < 21; i++)
	{
		nums[N - 1][i] = nums[N - 2][i];
	}
	cout << nums[N - 1][arr[N - 1]] << "\n";
	return 0;
}

 

'알고리즘 > 백준' 카테고리의 다른 글

[백준 11066] 파일 합치기 (C++)  (0) 2024.06.24
[백준 10610] 30 (C++)  (0) 2024.06.23
[백준 1062] 가르침 (C++)  (0) 2024.06.20
[백준 1939] 중량제한 (C++)  (0) 2024.06.19
[백준 1269] 대칭 차집합 (C++)  (0) 2024.06.18