문제
1036번: 36진수 (acmicpc.net)
해결방법
- 최대값을 구하는 방법 각 자리수의 수마다 해당 수를 Z로 치환했을 때의 값과 차를 더해서 각각 36개의 배열에 저장한다. 예를 들어 12가 있을 때 2에 해당하는 배열에 1Z - 12의 값을 더해주고 1에 해당하는 배열에 Z2 - 12 값을 모두 더해준다. 모든 수를 더한 값에 배열에 들어있는 가장 큰 수 k 개를 뽑아 다 더해준다.
- 36진수 구현 클래스로 36진수를 구현하였다. 각 자리수 계산에 사용하기 위해 36진수를 10진수로 바꾸는 함수와 10진수를 36진수로 바꾸는 함수를 작성했다. 36진수 클래스는 36진수 문자열을 받아와서 거꾸로 저장해놓고 순서대로 더하도록 했다.
동작과정
- 모든 숫자를 더할 36진수 객체 sum과 각 숫자별 합을 구할 36진수 객체 36개가 있는 배열을 준비한다.
- 배열의 초기 값은 모두 0으로 설정한다.
- 문자열을 입력 받으면서 sum에 모두 더해주고 문자열을 돌면서 해당 자리의 숫자를 Z로 치환한 차이 값을 해당 숫자 배열에 더해준다.
- 배열의 내용을 모두 pq에 담고 그중 k개 만큼을 뽑아 sum에 더해준다.
코드
import java.io.*;
import java.util.Arrays;
import java.util.PriorityQueue;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
int N = Integer.parseInt(in.readLine());
Decimal[] plus = new Decimal[36];
for(int i = 0; i < 36; i++)
plus[i] = new Decimal("0");
Decimal sum = new Decimal("0");
for(int i = 0; i < N; i++) {
String s = in.readLine();
sum.plus(new Decimal(s));
for(int j = 0; j < s.length(); j++) {
int value = getValue(s.charAt(j));
plus[value].plus(s.charAt(j), s.length()-1-j);
}
}
int K = Integer.parseInt(in.readLine());
PriorityQueue<Decimal> pq = new PriorityQueue<>();
pq.addAll(Arrays.asList(plus));
for(int i = 0; i < K; i++) {
sum.plus(pq.poll());
}
out.write(sum.getDigit());
out.flush();
}
static int getValue(char value){
if(Character.isDigit(value))
return value - '0';
else
return 10 + value - 'A';
}
static char toDecimal(int num) {
if(num < 10)
return (char)(num + '0');
else
return (char)(num - 10 + 'A');
}
static class Decimal implements Comparable<Decimal>{
String digit;
int length;
public Decimal(String digit) {
StringBuilder sb = new StringBuilder();
for(int i = digit.length()-1; i >= 0; i--)
sb.append(digit.charAt(i));
this.digit = sb.toString();
this.length = digit.length();
}
public void plus(Decimal other) {
int length = Math.max(other.length, this.length);
StringBuilder sb;
sb = new StringBuilder();
int before = 0;
for(int i = 0; i < length; i++) {
int o1 = 0;
int o2 = 0;
if(this.length > i) {
if (Character.isDigit(this.digit.charAt(i)))
o1 = this.digit.charAt(i) - '0';
else
o1 = 10 + this.digit.charAt(i) - 'A';
}
if(other.length > i) {
if (Character.isDigit(other.digit.charAt(i)))
o2 = other.digit.charAt(i) - '0';
else
o2 = 10 + other.digit.charAt(i) - 'A';
}
int sum = (o1 + o2 + before);
sb.append(toDecimal(sum % 36));
before = sum / 36;
}
if(before != 0)
sb.append(toDecimal(before));
this.digit = sb.toString();
this.length = digit.length();
}
public void plus(char c, int index) {
StringBuilder sb = new StringBuilder();
sb.append(toDecimal(35 - getValue(c)));
for(int i = 0; i < index; i++)
sb.append("0");
this.plus(new Decimal(sb.toString()));
}
public String getDigit() {
StringBuilder sb = new StringBuilder();
boolean zeroCount = true;
for(int i = digit.length()-1; i >= 0; i--) {
if(digit.charAt(i) == '0' && zeroCount)
continue;
if(digit.charAt(i) != '0')
zeroCount = false;
sb.append(digit.charAt(i));
}
if(sb.length() == 0)
sb.append('0');
return sb.toString();
}
@Override
public int compareTo(Decimal o) {
String s1 = this.getDigit();
String s2 = o.getDigit();
if(s1.length() == s2.length()) {
return s2.compareTo(s1);
}
return s2.length() - s1.length();
}
}
}