-
문제적남자 131회 - 로꾸꺼프로그래밍/알고리즘 2017. 12. 5. 20:19
문제
어떤 숫자를 반전해 그 두 개의 숫자를 더한 값을 다시 반전해 더하는 과정을 3번 반복할 때 나올 수 있는 4자리 숫자 중 가장 큰 회문 숫자는?
(단, 모두 같은 숫자 X)
먼저 회문(Palindrome)은 앞으로 읽으나, 뒤로 읽으나 같은 단어나 문장을 말하는데,
회문 숫자라 함은 '회문의 성질을 지닌 숫자', 즉 앞으로 읽으나 뒤로 읽으나 그 값이 같은 수를 말한다.
예를 들어서 '9999', '7447', '818', '565676565' 등등이 있을 것이다.
문제 해결에서 고려해야 할 것은 다음과 같다.
1) 길이제한: 결과값은 4자리 수이므로 (1000<=결과값<=9999)를 만족해야 한다.
이때, 조건에서 4자리 수가 모두 같은 숫자로 이루어질 수 없다고 했으므로 (1001<=결과값<=9889)이다.
2) 회문판별: a==d, b==c를 동시에 만족하면 회문이다.
3) 회문의 제한: '4자리 수의 결과 값이 모두 같은 숫자로 이뤄질 수 없다'라고 하므로 '9999', '8888'과 같은 숫자들은 나올 수 없다.
결과값의 각 자릿수를 a(천의 자리), b(백의 자리), c(십의 자리), d(일의 자리)라고 하면, (a==b==c==d)는 False가 되어야 한다.
그런데, 회문에서 a==d, b==c이므로 (a==b)가 False인지만 체크해주기만 하면 된다.
4) 숫자 하나와 그 숫자를 반전한 숫자를 더할 때 자릿수 문제:
어떤 수 n과 n을 반전한 수를 더할 때, n의 각 자릿수를 a(천의 자리), b(백의 자리), c(십의 자리), d(일의 자리)라고 하므로
(n+n을 반전한 수)=n+(d*1000+c*100+b*10+a)로 구할 수 있다.
그러나, n이 3자리 수일 때 문제가 발생한다. 예를 들어서 n=100일때, n이 3자리 수이므로 a=0, b=1, c=0, d=0이다.
100을 반전하면 001, 즉 1이 되어야 정상적인 결과이지만 위 식에 따르면 (d*1000+c*100+b*10+a)=0+0+1*10+0=10이 된다.
따라서 n이 1000보다 작을 때는 (n+n을 반전한 수)=n+(d*100+c*10+b)로 계산해야 한다.
그렇게 되면 n=100일때 a=0, b=1, c=0, d=0이고 (d*100+c*10+b)=0+0+1=1으로 제대로 나온다.
물론 최대값을 만드는 처음 수가 3자리 이하일 리는 없겠지만 그래도 재미삼아 만들어 보자.
2자리일 때 반전한 수는 (d*10+c)이고, 1자리일 때는 반전할 거 없다!
크크어차피 최대값을 찾는 게 목적이니 코드는 3자리수일 때까지만 처리해 두겠다.
문제적남자에서는 타일러가 665로 9119를 만들었고, 박경이 724로 9559를 만들어 문제를 해결했다.
그런데 두 분 다 게싱(Guessing)으로 하셨다...! ㄷㄷ
고려대의 힘코드 1
100~999의 수를 하나씩 집어넣어서 시뮬레이션 하는 방식이다.12345678910111213141516171819202122232425262728293031323334#include <stdio.h>int main(){int max=0;for(int n=100; n<=999; n++){int sum=n;int a, b, c, d;a/*천의 자리*/=sum/1000;b/*백의 자리*/=sum/100%10;c/*십의 자리*/=sum/10%10;d/*일의 자리*/=sum%10;if(sum>999) sum+=d*1000+c*100+b*10+a;else sum+=d*100+c*10+b;for(int i=0; i<3; i++){a/*천의 자리*/=sum/1000;b/*백의 자리*/=sum/100%10;c/*십의 자리*/=sum/10%10;d/*일의 자리*/=sum%10;if(sum>999) sum+=d*1000+c*100+b*10+a;else sum+=d*100+c*10+b;}a/*천의 자리*/=sum/1000;b/*백의 자리*/=sum/100%10;c/*십의 자리*/=sum/10%10;d/*일의 자리*/=sum%10;if(sum>9889||sum<1001) continue;else if(a!=d || b!=c) continue;else if(a==b) continue;else{printf("n:%d sum:%d\n", n, sum, a, b, c, d);if(sum>max) max=sum;}}printf("\nmax: %d", max);}cs 문제에서 한 지시처럼 처음 수 n과 n을 반전한 값을 더한 뒤, 이처럼 결과와 결과를 반전해 더하는 과정을 3번 반복하는 것을 그대로 표현했다.
최대값은 max라는 변수를 만들어 둔 뒤 최종 실행 결과가 저장되는 sum과 비교해 갱신할지를 결정하게 하였다.
코드 1 실행결과
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108n:125 sum:7337n:129 sum:5115n:132 sum:4884n:134 sum:2882n:139 sum:5995n:142 sum:4774n:145 sum:7117n:159 sum:4884n:161 sum:1991n:171 sum:1881n:174 sum:5115n:175 sum:9559n:181 sum:2662n:191 sum:2552n:192 sum:6996n:195 sum:9339n:199 sum:6226n:224 sum:7337n:228 sum:5115n:229 sum:9559n:231 sum:4884n:233 sum:2882n:238 sum:5995n:241 sum:4774n:244 sum:7117n:258 sum:4884n:260 sum:1991n:269 sum:9119n:270 sum:1881n:273 sum:5115n:274 sum:9559n:280 sum:2662n:290 sum:2552n:291 sum:6996n:294 sum:9339n:298 sum:6226n:323 sum:7337n:327 sum:5115n:328 sum:9559n:330 sum:4884n:332 sum:2882n:337 sum:5995n:340 sum:4774n:343 sum:7117n:357 sum:4884n:368 sum:9119n:372 sum:5115n:373 sum:9559n:390 sum:6996n:393 sum:9339n:397 sum:6226n:422 sum:7337n:426 sum:5115n:427 sum:9559n:431 sum:2882n:436 sum:5995n:442 sum:7117n:456 sum:4884n:467 sum:9119n:471 sum:5115n:472 sum:9559n:492 sum:9339n:496 sum:6226n:521 sum:7337n:525 sum:5115n:526 sum:9559n:530 sum:2882n:535 sum:5995n:541 sum:7117n:555 sum:4884n:566 sum:9119n:570 sum:5115n:571 sum:9559n:591 sum:9339n:595 sum:6226n:620 sum:7337n:624 sum:5115n:625 sum:9559n:634 sum:5995n:640 sum:7117n:654 sum:4884n:665 sum:9119n:670 sum:9559n:690 sum:9339n:694 sum:6226n:723 sum:5115n:724 sum:9559n:733 sum:5995n:753 sum:4884n:764 sum:9119n:793 sum:6226n:822 sum:5115n:823 sum:9559n:832 sum:5995n:852 sum:4884n:863 sum:9119n:892 sum:6226n:921 sum:5115n:922 sum:9559n:931 sum:5995n:951 sum:4884n:962 sum:9119n:991 sum:6226max: 9559--------------------------------Process exited after 0.1985 seconds with return value 0계속하려면 아무 키나 누르십시오 . . .cs 역시 9559로 답이 잘 나온다.
그러고 보니 타일러의 '처음 수'는 665였는데, 최대값과 같이 9559의 결과가 나오는 수는 670, 고작 5 차이였다..ㅠㅠ
코드 2
그냥 저렇게 반복문 4번 돌려도 된다.12345678910111213141516171819202122232425262728#include <stdio.h>int main(){int max=0;for(int n=100; n<=999; n++){int sum=n;int a, b, c, d;for(int i=0; i<4; i++){a/*천의 자리*/=sum/1000;b/*백의 자리*/=sum/100%10;c/*십의 자리*/=sum/10%10;d/*일의 자리*/=sum%10;if(sum>999) sum+=d*1000+c*100+b*10+a;else sum+=d*100+c*10+b;}a/*천의 자리*/=sum/1000;b/*백의 자리*/=sum/100%10;c/*십의 자리*/=sum/10%10;d/*일의 자리*/=sum%10;if(sum>9889||sum<1001) continue;else if(a!=d || b!=c) continue;else if(a==b) continue;else{printf("n:%d sum:%d\n", n, sum, a, b, c, d);if(sum>max) max=sum;}}printf("\nmax: %d", max);}cs '프로그래밍 > 알고리즘' 카테고리의 다른 글
[NYPC2017_문제풀이] 알사탕 (2) 2017.12.02 [NYPC2016_예선문제] 마비노기 듀얼: 올바른 덱인가요? (0) 2017.12.02 [NYPC2016_예선문제] 넥슨은 다람쥐를 뿌려라 (0) 2017.12.02