본문 바로가기

알고리즘/SWEA

7103

static int N, sels[5];
static int table[32767 + 1];

static int __solution(int s, int v, int cnt)
{
	if (v == N)
	{
		//해당 수를 이루는 조합을 확인 할 수 있다.
		return 1;
	}

	if (cnt <= 4)
	{
		int ret = 0, ret1;
		for (int i = s; i <= N; i++)
		{
			int val = v + i * i;
			if (val > N)
				break;
			else if (val <= N)
			{
				if (val < N)
				{
					//해당 수를 이루는 조합을 확인 할 수 있다.
					table[val] += 1;
				}

				sels[cnt] = i; //선택 옵션
				ret1 = __solution(i, val, cnt + 1);
				if (ret1)
					ret += ret1;
				else
					sels[cnt] = 0; //선택 옵션
			}
		}
		return ret;
	}
	else
		return 0;
}

static int solution(void)
{
	scanf("%d", &N);
	int &ret = table[N];

	if (!ret)
		ret = __solution(1, 0, 1);

	return ret;
}

static void init_table(void)
{
	N = 32767;
	int ret = __solution(1, 0, 1);
	table[N] = ret;
}

라그랑주 네제곱수라는 정리와 연관되는 문제이다.

 

최근 여러 문제들을 재귀로 풀어나가면서 이 문제도 역시 재귀로 접근을 해보았다.

여러 삽질을 거치다가 원하는 출력이 제대로 나와서 테스트를 돌려보았지만 제한시간 초과가 발생하였다.

사실 알고리즘 문제 특성 상 해당 수를 이루는 네개의 제곱수들을 굳이 알 필요는 없었다.

그러나 풀이방향이 한번 잡혀버리고 나면 다른 방식으로 사고를 잘 하지 못하는 터라 제한시간 초과를 어떻게 해야 할 지 잘 몰랐다.

그래서 그냥 정답 코드 들 중 하나를 참조하였다. 여기서 나는 한동안 잊고있던 동적계획법이 사용 된 것을 볼 수 있었다.

사실 예전에는 문제를 풀 때 먼저 동적계획법을 고려하던 시기가 있었는데, 최근 재귀로만 문제를 해결하려 한 터라 이를 고려하지 못한 것이다. 앞으로는 편협한 사고방식을 좀 버려야 할 것 같다.

 

어쨌든 위 코드의 동작 방식은 아래와 같다.

4개의 제곱수 들 중 첫번째 제곱수는 1부터 확인 해 나가는 것이다.

두번째 제곱수는 첫번째 제곱수가 사용하는 값 이상, 세번째는 두번째 제곱수가 사용하는 값 이상을 확인 해 나가면서 타겟으로 하는 값을 만들 수 있는지 보는 것이다.

이 와 중에 4개 이하의 제곱수로 이루어진 값이 만들어 질 수 있다. 이를 미리 마련한 답안 테이블에 등록하는 것이다.

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

5648. 원자 소멸 시뮬레이션  (0) 2021.11.11
1953. 탈주범 검거  (0) 2021.11.11
2112. 보호 필름  (0) 2021.11.11
2105. 디저트 카페  (0) 2021.11.11
2382. 미생물 격리  (0) 2021.11.09