문제 링크
1036번: 36진수
36진법의 숫자는 0부터 9까지의 수와 알파벳 A에서 Z로 나타낸다. A부터 Z까지 알파벳은 10부터 35에 차례대로 대응한다. 36진법의 수 N개가 주어진다. 36진법 숫자(0-9, A-Z) 중에서 K개의 숫자를 고른다. 그러고 나서 N개의 수 모두에서 나타난 그 숫자를 Z로 바꾼다. 그 이후에 N개의 수를 모두 더한다...
www.acmicpc.net
주의사항
- JAVA를 사용하여 프로그램을 사용하였습니다.
- 백준에서 코드를 작성하였을 때 아래 형태에서 Main에서 결과가 출력되어야 합니다.
public class Main{
public static void main(String[] args){
}
}
문제 설명


접근 방법
이 문제에 핵심
1. 0 ~ 9, A ~ Z으로 표현되는 36진수가 존재합니다.
2. 36진수 중 K개를 선택해서 'Z'으로 N개의 문자열을 변경합니다.
3. 이 때 가능한 최대값을 결과로 출력합니다.
알고리즘 진행 순서.
1. 입력된 정보를 저장합니다.
2. 모든 알파벳에 대해서 'Z'으로 변경할 때 증가하는 수를 통해 K개 알파벳을 'Z'으로 변경한 뒤 수를 계산합니다.
3. 계산을 통해 얻은 최대 36진수의 값을 결과로 출력합니다.
'Z'으로 변경하기(그리디)
0 → Z으로 변경할 때에는 35만큼 수가 증가합니다.
예제입력 1.
1. 입력된 정보를 저장합니다.
N = 5
K = 7
[N개의 36진수 문자열]
GOOD
LUCK
AND
HAVE
FUN
2. 모든 알파벳에 대해서 'Z'으로 변경할 때 증가하는 수를 통해 K개 알파벳을 'Z'으로 변경한 뒤 수를 계산합니다.
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
A | B | C | D | E | F | G | H | I | J |
25(3) | 0 | 23(2) | 22(2), 22(1) |
21(1) | 20(3) | 19(4) | 18(4) | 0 | 0 |
K | L | M | N | O | P | Q | R | S | T |
15(1) | 14(4) | 0 | 12(2), 12(1) |
11(3), 11(2) |
0 | 0 | 0 | 0 | 0 |
U | V | W | X | Y | Z |
6(3) | 5(2) | 0 | 0 | 0 | 0 |
증가하는 수를 기준으로 내림차순 36진수 정렬
{ G, H, L, A, F, O, U, .....}
순서대로 K(7)개를 'Z'으로 변경
→ 변경되는 36진수 : G, H, L, A, F, O, U
변경된 문자열
ZZZD
ZZCK
ZND
ZZVE
ZZN
의 합을 구하면 최대값이 됩니다.
3. 계산을 통해 얻은 최대 36진수의 값을 결과로 출력합니다.
- BufferedReader를 사용하여 입력되는 정보를 저장합니다.
- 36진수를 받을 때 각 36진수가 'Z'으로 변경될 때 증가하는 값을 탐색합니다.
- 각 자릿수 기준 증가하는 값으로 내림차순으로 36진수를 정렬합니다.
- 정렬 기준으로 K개의 값을 선택해서 'Z'으로 변경을 진행합니다.
- 변경된 36진수의 합을 구해서 BufferedWriter 저장합니다.
- BufferedWriter에 저장된 결과를 출력합니다.
결과코드
import java.io.*;
import java.util.*;
public class Main {
//36진수의 증가하는 수치 저장하는 클래스
static class Info implements Comparable<Info>{
int idx;
int[] vals; //각 자릿수 증가하는 수치
public Info(int idx, int[] vals){
this.idx = idx;
this.vals = vals;
}
//각 자릿수 증가하는 수치 기준 내림차순 정렬
@Override
public int compareTo(Info o) {
for(int i=54;i>=0;i--){
if(this.vals[i] > o.vals[i]){
return -1;
}else if(this.vals[i] < o.vals[i]){
return 1;
}
}
return 0;
}
}
public static void main(String[] args) throws IOException {
//입력값 처리하는 BufferedReader
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//결과값 출력하는 BufferedWriter
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
int N = Integer.parseInt(br.readLine());
String[] words = new String[N];
//36진수 각 자릿수 증가하는 수치 초기화
List<Info> infos = new ArrayList<>();
for(int i=0;i<36;i++){
infos.add(new Info(i, new int[55]));
}
//문자열 입락 받은 후, 각 36진수 증가하는 수치 계산
for(int i=0;i<N;i++) {
words[i] = br.readLine().trim();
int len = words[i].length();
for(int j=0;j<len;j++){
char c = words[i].charAt(j);
//'A' ~ 'Z'일 때
if(c >= 'A'){
infos.get(c-'A'+10).vals[len - j - 1] += 'Z' - c;
}else{ // 0 ~ 9일 때
int temp = Character.getNumericValue(c);
infos.get(temp).vals[len - j - 1] += 35 - temp;
}
}
}
//증가하는 수치가 36이상일 때 올림 적용
for(Info info : infos){
for(int i=0;i<55;i++){
if(info.vals[i] >= 36){
//올림 적용
info.vals[i+1] += info.vals[i] / 36;
//남은 값 계산
info.vals[i] %= 36;
}
}
}
int K = Integer.parseInt(br.readLine());
//각 자릿수 증가하는 수 기준 내림차순 정렬 진행
Collections.sort(infos);
//변경해야 하는 값 설정
Set<Integer> change = new HashSet<>();
//순서대로 K개 'Z'으로 변경할 36진수 선택
for(int i=0;i<K;i++){
change.add(infos.get(i).idx);
}
//변경해야 하는 K개 36진수 'Z'으로 변경
for(int changeVal : change){
String c;
if(changeVal >= 10){
c = String.valueOf((char)(changeVal - 10 + 'A'));
}else{
c = String.valueOf((char)(changeVal + '0'));
}
for(int i=0;i<N;i++){
words[i] = words[i].replaceAll(c, "Z");
}
}
int[] result = new int[55];
//변경한 값에 대해서 36진수의 합 구하기.
for(int i=0;i<N;i++){
int len = words[i].length();
for(int j=0;j<len;j++){
int temp;
if(words[i].charAt(j) >= 'A'){
temp = words[i].charAt(j) - 'A' + 10;
}else{
temp = Character.getNumericValue(words[i].charAt(j));
}
result[len - j - 1] += temp;
}
}
//각 자릿수에 대한 올림 진행
for(int i=0;i<55;i++){
if(result[i] >= 36){
result[i+1] += result[i] / 36;
result[i] %= 36;
}
}
boolean flag = false;
//각 자릿수에 맞는 값들을 36진수 형태로 변경
for(int i=54;i>=0;i--){
if(result[i] == 0 && !flag){
continue;
}
flag = true;
if(result[i] >= 10){
bw.write(String.valueOf((char)(result[i] - 10 + 'A')));
}else{
bw.write(String.valueOf(result[i]));
}
}
//만약 결과가 0일 때
if(!flag){
bw.write("0");
}
bw.flush(); //결과 출력
bw.close();
br.close();
}
}
'백준' 카테고리의 다른 글
[백준, Java] 25513번, 빠른 오름차순 숫자 탐색(BFS) (0) | 2024.08.01 |
---|---|
[백준, Java] 27211번, 도넛 행성(BFS) (0) | 2024.07.30 |
[백준, Java] 25605번, 입맛이 까다로운 코알라가 유칼립투스 잎을 행복하게 먹을 수 있는 방법, [DP] (0) | 2024.07.10 |
[백준, Java] 1562번, 계단 수, [DP, 비트마스킹] (0) | 2024.07.02 |
[백준, Java] 1513번, 경로 찾기, [DP] (2) | 2024.06.25 |
댓글