The Way
백준 4881번: 자리수의 제곱 본문
백준 온라인 저지(BOJ) 4881번 문제
https://www.acmicpc.net/problem/4881
1. 문제 요약
각 자리수를 제곱하여 더하여 만들어지는 수열이 있다.
초기 숫자 두 개가 주어질 때, 같은 숫자가 나올 때까지의 수열의 길이의 합이 가장 작을 때 그 합은 얼마인가?
2. 알고리즘
문제에서 두 개의 사이클이 소개되었다.
하나는 89, 145, 42, 20, 4, 16, 37, 58이고 하나는 1이다.
따로 계산을 해보면 알겠지만 이 두 개의 사이클이 유일한 사이클이다.
따라서 수열이 저 사이클에 포함될 때 까지 계산해준 뒤,
서로 다른 사이클이면 불가능
같은 사이클일 경우, 첫 도착지점이 같으면 공통 부분을 소거해주고
첫 도착지점이 다를 경우 (ex 89, 37처럼 될 경우) 짧은 방향으로 사이클을 돌아야 한다
(위 예시에서는 37에서 출발해서 37->58->89로 가야 한다)
3. 코드
#include <iostream> #include <vector> using namespace std; int arr[9] = { 89, 145, 42, 20, 4, 16, 37, 58, 1 }; int cal(int n) { int r = 0; while (n) { r += (n % 10) * (n % 10); n /= 10; } return r; } bool in(int n) { for (int i = 0; i < 9; ++i) { if (n == arr[i]) return true; } return false; } int main() { int a, b; while (true) { scanf("%d %d", &a, &b); if (a + b == 0) break; printf("%d %d ", a, b); vector<int> aa; vector<int> bb; while (in(a) == false) { aa.push_back(a); a = cal(a); } while (in(b) == false) { bb.push_back(b); b = cal(b); } if (a == 1 ^ b == 1) { printf("0\n"); continue; } if (a == b) { while (!aa.empty() && !bb.empty() && aa.back() == bb.back()) { aa.pop_back(); bb.pop_back(); } printf("%d\n", aa.size() + bb.size() + 2); } else { int ai, bi; for (int i = 0; i < 8; ++i) { if (a == arr[i]) ai = i; if (b == arr[i]) bi = i; } int r = ai > bi ? ai - bi : bi - ai; printf("%d\n", aa.size() + bb.size() + 2 + (r > 4 ? 8 - r : r)); } } return 0; }
'PS > 백준 온라인 저지' 카테고리의 다른 글
백준 13623번: Zerinho ou Um (0) | 2018.01.09 |
---|---|
백준 9664번: NASLJEDSTVO (0) | 2018.01.09 |
백준 2606번: 바이러스 (0) | 2017.12.07 |
백준 2178번: 미로 탐색 (0) | 2017.12.07 |
백준 11722번: 가장 긴 감소하는 부분 수열 (0) | 2017.11.28 |
Comments