mojo's Blog

[백준 1699] 제곱수의 합 본문

백준/Dynamic Programming

[백준 1699] 제곱수의 합

_mojo_ 2021. 7. 9. 16:05

문제 링크 => 1699번: 제곱수의 합 (acmicpc.net)

 

1699번: 제곱수의 합

어떤 자연수 N은 그보다 작거나 같은 제곱수들의 합으로 나타낼 수 있다. 예를 들어 11=32+12+12(3개 항)이다. 이런 표현방법은 여러 가지가 될 수 있는데, 11의 경우 11=22+22+12+12+12(5개 항)도 가능하다

www.acmicpc.net


다이나믹 프로그래밍 문제이다.

 

자연수 N을 제곱수들의 합으로 표현할 때에 그 항의 최소개수를 구해야 하는 문제이다.

 

첫번째로 접근한 방법은 다음과 같다.

 

d[1] = 1 / 1개

d[2] = d[1] + d[1] / 2개

d[3] = d[1] + d[1] + d[1] / 3개

d[4] = 4 / 1개

d[5] = d[4] + d[5-4] / 1 + 1 = 2개

d[6] = d[4] + d[6-4] / 1 + 2 = 3개

d[7] = d[4] + d[7-4] / 1 + 3 = 4개

d[8] = d[4] + d[8-4] / 1 + 1 = 2개

d[9] = 9 / 1개

d[10] = d[9] + d[10-9] / 1 + 1 = 2개

d[11] = d[9] + d[11-9] / 1 + 2 = 3개

d[12] = d[9] + d[12-9] / 1 + 3 = 4개

...

 

이런식으로 코드를 제출하였더니 실패가 떳다.

 

반례를 생각해보니 12 에서 문제가 발생하였다.

 

d[12] = d[9] + d[3] => 4개인 반면에,  d[12] = d[4] + d[4] + d[4] = d[4] + d[8] => 3개일수도 있다.

 

또한 d[61] = d[49] + d[12] => 8개인 반면에,   d[61] = d[36] + d[25] => 2개일수도 있다.

 

즉, 위방법에서 구한 d[x] 값과 1~x 사이에 제곱수 y 값과 x-y 값의 제곱수들의 합에 대한 경우도 고려해줘야 한다.

 

즉, for문을 돌려서 d[x] = min(d[x], d[y] + d[x-y]) 값을 할당해주는것이 핵심이다. (y = 1, 4, 9, 16, 25, ... , sqrt(x)*sqrt(x))

 

풀이 code


#define _CRT_SECURE_NO_WARNINGS
#include <string>
#include <stdio.h>
#include <math.h>
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <time.h>
#define INF 100000000
#define endl '\n'

using namespace std;

int d[100001];

void solve(int n) {
	d[1] = 1, d[2] = 2, d[3] = 3;
	for (int i = 2; i <= sqrt(n); i++) {
		d[i * i] = 1;
	}
	int x=4;
	for (int i = 5; i <= n; i++) {
		if (d[i]) {
			x = i;
			continue;
		}
		d[i] = d[x] + d[i - x];
		for (int j = 1; j <= sqrt(i); j++) {
			d[i] = min(d[i], d[j * j] + d[i - j * j]);
		}
	}
	cout << d[n];
}

int main() {
	ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);

	int n;
	cin >> n;
	solve(n);

	return 0;
}

'백준 > Dynamic Programming' 카테고리의 다른 글

[백준 2248] 이진수 찾기  (0) 2021.07.13
[백준 13398] 연속합 2  (0) 2021.07.11
[백준 2225] 합분해  (0) 2021.07.08
[백준 2240] 자두나무  (0) 2021.07.04
[백준 2293] 동전 1  (0) 2021.07.04
Comments