어떻게 풀까?
주목해야할 부분은 3 조각 부터 5 조각만 확인한다는 사실입니다. 따라서, 해당 문제를 풀 때에는 앞에서부터 반복문을 통해서 3 자리, 4 자리, 5자리를 확인하며 가장 최소로 만들 수 있는 난이도를 저장해 가면서 배열을 만들어 나가면, 마지막에 나오는 수가 최소 원주율 난이도인 것입니다.
12341234의 경우를 예로 보겠습니다.
123의 경우에는 난이도가 1 입니다.
1234의 경우에도 난이도는 1 입니다.
12341의 경우에는 난이도가 10 입니다.
123412의 경우에는
123의 난이도 1 + 412의 난이도 10인 11이 될 것 입니다.
1234123의 경우에는
1. '123'의 난이도 1과 '4123'의 난이도 10을 더한 11
2. '1234'의 난이도 1과 '123'의 난이도 1을 더한 2
2 가지 난이도를 얻을 수 있습니다. 이 중에 최솟값이 2이므로 '1234123'에서는 2 난이도가 최소라는 것을 알 수 있습니다.
12341234의 경우에는
1. '123'의 난이도 1과 '41234'의 난이도 10을 더한 11
2. '1234'의 난이도 1과 '1234'의 난이도 1을 더한 2
3. '12341'의 난이도 10과 '234'의 난이도 1을 더한 11
3 가지 난이도를 얻을 수 있습니다. 이 중에 최솟값이 2 이므로, 마지막에 결과값으로 얻는 난이도는 2가 되는 것입니다!
따라서,
i 까지 올 수 있는 최소 난이도가 diffulcyt(i)라고 하고, a 부터 b 까지의 난이도를 classify(a,b)를 이용해 구할 수 있다고 한다면
점화식은 아래와 같습니다.
difficulty(i) = min( difficulty(i-2) + classify(i-2, i), difficulty(i-3) + classify(i-3,i), difficulty(i-4) + classify(i-4,i) )
difficulty는 배열에 저장하면 해당 인덱스까지 오는데 걸리는 최소 난이도 값이 저장됩니다.
그리고, 위의 점화식에 따라서 배열을 한번만 훑어보면 결국 마지막에는 최종적으로 계산되는 난이도가 저장되는 것입니다.
classify 함수에는 위 문제에 적힌 조건을 만족시킬수 있도록 난이도를 판별해주는 함수를 작성하면 됩니다!
코드
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | #pragma once //원주율 외우기 //알고스팟 //https://algospot.com/judge/problem/read/PI #include<cstdio> #include<cstring> char str[10001]; int dp[10001] = { 0 }; int min(int i1, int i2) { return i1 < i2 ? i1 : i2; } int abs(int i1) { return i1 > 0 ? i1 : -i1; } int PI() { int t; scanf("%d\n", &t); while (t--) { scanf("%s\n", str); int len = strlen(str); for (int i = 1; i <= len; i++) { dp[i] = 987654321; } for (int i = 0; i < len; i++) { char c[2]; c[i%2] = str[i]; c[(i+1)%2] = str[i + 1]; int diff = str[i + 1] - str[i]; bool hFlag[4] = { true, true, true, true }; hFlag[0] = c[0] == c[1]; hFlag[1] = abs(diff) == 1; for (int l = 2; l < 5; l++) { if (i + l >= len) break; int hard; hFlag[0] &= str[i + l] == str[i + l - 1]; hFlag[1] &= str[i + l] - str[i + l - 1] == diff; hFlag[2] &= str[i + l] == c[(i + l) % 2]; hFlag[3] &= str[i + l] - str[i + l - 1] == diff; if (hFlag[0]) hard = 1; else if (hFlag[1]) { hard = 2; } else if (hFlag[2]) { hard = 4; } else if (hFlag[3]) { hard = 5; } else { hard = 10; } dp[i + l + 1] = min(dp[i + l + 1], dp[i] + hard); } } printf("%d\n", dp[len]); } return 0; } | cs |
'공부 > 알고리즘 문제풀이' 카테고리의 다른 글
[알고스팟] 타일링 방법의 수 세기 (0) | 2018.06.16 |
---|---|
[알고스팟] Quantization (2) | 2018.06.15 |
[알고스팟] 합친 LIS (0) | 2018.06.14 |
[알고스팟] 최장 증가 부분 수열 LIS (longest increasing subsequence) (0) | 2018.06.14 |
[알고스팟] 삼각형 위의 최대 경로 (0) | 2018.06.12 |