자바는... 느리다.

그런데 생각보다 빠르다. 



일반적으로 알고리즘을 풀 때, 자바의 경우는 scanner를 자주 사용한다. 아무래도 여러가지 부가기능이 붙어있으므로 사용하기 편한면 때문에 다들 많이 사용하는 것 같다.


다만, 자바의 경우 입력이 많을 때 , scanner를 써서 시간초과가 날 수 있다. 뿐만 아니라 그때 그때 출력할 경우에도 시간 초과가 날 수 있다.


오늘의 완죤 쉬운 문제 하나를 소개하겠다. 


이름하야 수 정렬하기3  https://www.acmicpc.net/problem/10989


솔루션은 간단한데, 직접 정렬을 할 경우 시간초과에 걸리게 된다. N 사이즈가 천만이기 때문에, log조차 붙이는게 조심스럽다.


그런데 보면 최대 값이 10000이다 따라서 카운팅소트를 진행하시면 되겠다.


근데 이문제의 핵심은 이거라기보다... 


인풋을 얼마나 빨리 받을 수 있냐에 있다. 


자바용 쓸만한 빠른속도로 입력받기 소스를 소개하겠다.



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
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
 
public class Main {
    public static void main(String[] args) throws IOException{
 
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();
 
        int N = Integer.parseInt(br.readLine());
        int[] arr = new int[10010];
 
        for (int i = 0; i< N;i++){
            arr[Integer.parseInt(br.readLine())]++;
        }
 
        for(int i =0; i<= 10000; i++){
            while(arr[i] != 0){
                sb.append(""+i+"\n");
                arr[i]--;
            }
            
        }
        System.out.println(sb.toString());
    }
 
}
 
cs

한꺼번에 모아서 입력을 받고 한꺼번에 모아서 출력한다. 라는 쉬운 개념인데, c++의 scanf, printf 보다 성능이 좋다.

이런 쉬운 것에 불필요한 설명을 덧붙이는 것은 좀 귀찮으니... 다들 소스코드 이해하는데 문제 없으리라 보고 이정도만 포스팅 하도록 하겠다.

다만 주의할 것이 StringBuilder를 사용하지 않고 string간의 +연산을 사용할 경우, 

자바를 아시는 분들은 아실 수도 있지만, 당연히 시간 초과가 난다. String간 + 연산에 관해서는 검색해서 찾아보시길 바랍니다. 



딱히 필요해서 정리하는 것은 아닌데 이런 것이 정리하고 공유하는게 다른 분들이 공부하기 더 쉬울 것 같아 포스팅 한다.


1. dovelet : www.dovelet.com

더블릿은 부분유료 사이트이다. 모든 문제를 볼수는 있다. 다만 1,2,3계단만 공짜로 채점 받을 수 있다. 즉 4단계 이상의 문제를 제출해 볼 수는 없다. 1,2,3단계는 기본적인 입출력, 반복문등을 연습하는 기초적인 단계이므로 알고리즘을 공부하기로 마음 먹은 사람에게 거의 필요없는 문제들이 많기 떄문에( 물론 코딩 속도를 올리는 용도로는 효과적이라는 이야기도 있다. ) 사실상 유료사이트라고 봐도 될 것 같다.


특징

장점

      1.  계단별로 특정 알고리즘의 설명, 수도코드, 소스코드등이 첨부되어 있어 혼자 공부하기 쉽다. 
      2. 특정 알고리즘을 배운 다음에 그 밑에 그 알고리즘으로 풀리는 문제들이 있다. 그 문제들을 풀어보며 감을 익힐 수 있다. 
      3.  만약 제출한 코드가 틀렸을 경우 틀린 testcase를 볼 수 있다. 

단점

      1.  제출한 코드가 틀렸을 경우에 틀린 testcase를 보여주는게 항상 좋은 것은 아니다.(실전 처럼 연습할 때 불편할 경우가 많다.)
      2.  테스트케이스가 빡빡하지 않다. 통과되지 말아야할 소스코드가 통과되는 경우가 왕왕 있었던 것으로 기억한다.
      3.  제대로 공부를 할 요량으로 이 사이트를 사용하려면 3만원? 정도되는 가격을 지불해야한다. (평생 사용 요금이다.)



2. 백준 온라인 저지 : www.acmicpc.net 

백준은 완전 무료사이트로 모든 문제를 공짜로 풀어볼 수 있다. 유아이도 상당히 이쁜 편이다. 직관적이고 상당히 많은 문제를 풀어 볼 수 있다. acmicpc관련 문제 + 올림피아드 관련 문제들이 많아 이 쪽 준비를 하는 사람들에게는 상당히 도움이 되는 사이트다. 질문 게시판들도 있어 모르는 문제를 물어볼 수 있다. 갓갓갓님들이 잘 답변해주신다고....



특징

장점

      1. 공짜다.
      2. 문제양이 상당히 많다.
      3. UI가 이쁘다.
      4. 갓갓갓님들이 주로 상주하는 사이트이고, 또 질문을 올릴 경우 이 갓갓갓 분들이 답변을 잘해주신다.
      5. 테스트 데이터가 빡빡한 편이라 어셉이 나지 말아야할 코드가 어셉이 나는 경우는 거의 없다. 있다고 해도 사람들이 찾아서 데이터를 보강해준다.  
      6. 그룹을 만들어 아는 사람들끼리 가상의 대회를 열어볼 수 있다.

단점

      1.  아직 분류 기능이 활성화 되어 있지 않아서 분류되어 있는 문제가 적다. 특정 알고리즘으로 푸는 문제를 분류탭에서 찾아보면 문제가 너무 적거나 말도안되게 어렵거나... 
      2. 친구기능이 없다. ㅠ

기타

      1. icpc.me/[문제번호] 라는 url로 접속하면 해당 문제로 바로 이동 가능하다.
         예) 자물쇠 문제 : icpc.me/1514
      2. BOJ 슬랙이 있다. 질문을 게시판으로 해도되지만 슬랙에 올려도 된다. 슬랙에 올리는 편이 더 자세한 답변을 들을 수 있는 것 같다.  



3. UVA, live archive: https://uva.onlinejudge.org/ ,https://icpcarchive.ecs.baylor.edu/

 되게 짜증나는 외국 사이트인데 처음 시작하는 사람에게는 별로 추천해주고 싶지는 않다. 문제양은 정말 많지만... 데이터 자체가 틀렸을 경우가 왕왕이아니라 아주 많다. (정답인 코드가 틀린다던가 하는) 뿐만아니라 개행문제등을 이유로 틀렸습니다가 뜨는 문제들이 너무많다.(스트레스... ) 


특징

장점

      1. 공짜다.
      2. 문제양이 상당히 많다.
      3. acmicpc관련 문제는 거의 대부분 있다.

단점

      1. 내가 알기로 문제 분류기능 따위는 없다. UI도 불편... 
      2. acm문제들 중 예선문제는 수록되어 있지 않다.
      3. acm문제들이 대부분 수록되어있으나 데이터가 틀린 경우가 너무 많다.
      4. 틀리기만 하는 것도아니고 데이터가 약한 것도 너무 많다.
      5. 개행등으로 틀렸습니다가 뜨는 경우가 많다.

기타

      1. 가상의 대회를 열어볼 수 있다. https://icpcarchive.ecs.baylor.edu/uhunt/
      2. 근데 위에 저게... 시간이나 문제링크등이 이상하게 되어있다. 짜증남... 


4. codeforces, topcoder : www.codeforces.com  , www.topcoder.com

 온라인 저지라기보다 컨테스트 사이트다. codeforces는 러시아 것이고 topcoder는 미국 것이다. 문제는 둘다 영어로 제공되며 게임처럼 레이팅을 경쟁할 수 있다. 레이팅별로 색깔이 달라지는데 빨간색, 노란색, 보라색 티어(?)가 있다. 롤로 치면 마스터, 다이아, 플레티넘 같은 것이라고 보면 된다. 레이팅 올리는 재미가 있으며 정규 컨테스트에서만 레이팅이 변경된다. 둘다 가상의 컨테스트를 열어볼 수 있고 DIV1/DIV2로 나누어져있는데 DIV1은 상위리그, DIV2는 하위리그다. 처음 시작 하는 분들은 DIV2 대회로 시작하시면 되겠다.

특징

장점

      1. 공짜다.
      2. 게임처럼 참가할 수 있다. 롤 레이팅 올리는 느낌이다. 
      3. 에디토리얼이라고 문제풀이가 제공된다. 따라서 보면서 공부할 수 있다.
      4. 둘다 핵 개념이 있는데 컨테스트중에 제공되는 테스트 케이스는 약한 테스트 케이스다. 따라서 어셉이나도 최종적으로 어셉이 아닐 수 있다. 이런 부분 때문에 각별히 예외나 시간복잡도 신경써야한다. 다른사람이 여러분의 소스코드를 읽고 틀린 데이터를 만들어 여러분의 소스코드를 공개할 수 있다.
      5. 반대로 문제를 잘 못풀어도 핵을 잘해서 점수를 딸 수 있다. 다른 사람의 소스코드에서 예외를 찾아 던지면 추가 점수를 얻을 수 있다.  

단점

      1.  소스코드를 읽기가 힘들다. 각종 define과 typedef의 연속... 
      2.  콘테스트에서 영어에 의해서 디버프를 받을 수 밖에 없다. 부족한 영어실력을 알고리즘 실력으로 극복해야한다. ㅠㅠ
      3.  핵당하면 괜히 기분이 나쁘다.
      4. 사이트가 빠른 편은 아니다. (아무래도 한 컨테스트당 몇천명의 사람이 몰리기 때문인 것 같다.) 




자세히 소개는 안했지만 다른  좋은 곳들도 많다. 

주로 사용하는 사이트만 리뷰하고 자주 사용하지 않은 사이트들은 정리하지 않았다. 잘못된 정보를 줄 수도 있기 때문에...

아래는 그외 사이트들이다.


알고스팟 : www.algospot.com 

수학관련 문제 - 프로젝트 오일러 :  http://projecteuler.net/ 

수학관련 문제 - 프로젝트 오일러(한국) : http://euler.synap.co.kr/ 

아주대학교 알고리즘 온라인 저지 라비다 : http://www.lavida.us/ 



원 출처 : 모름



문제 링크 : 

https://www.acmicpc.net/problem/1514


문제 설명 : 

 숫자로 이루어진 문자열 2개가 주어지는데 첫 번째 문자열을 두번 째 문자열로 바꾸는데 드는 최소 코스트를 구하는 문제.


 문자열에 가할 수 있는 연산은 최소 1개에서 최대 3개를 선택해서 그 값을 한꺼번에 최대 1이상 3이하 증가/감소 시킬 수 있다. 물론 숫자는 0~9까지만 사용하며 0밑으로 내려가면 9로, 9 이상으로 올라가면 0으로 다시 돌아간다. 즉 숫자를 회전시키는 것이라고 볼 수 있다.



dp 상태 정의 :


dy[n][t1][t2] :: 첫번째 부터 n번째까지 자물쇠를 돌렸을 때 n번째 숫자가 t2고 n-1번째 숫자가 t1이고 1~n-2까지의 숫자는 목표 다이얼을  완성한 상태 

t1과 t2는 0~9까지 값을 가진다.



전처리가 좀 필요한데 다른 분들은 수식만으로 구하신 것 같지만 나는 멍청함으로 수식따위 구하지 않고 직접 bfs를 사용해서 구했다.


 가장 기초적인 전처리 방법은  


 pre[s1][s2][s3][t1][t2][t3] :: 세 다이얼이 s1, s2, s3일 때 t1, t2, t3로 변환하기 위한 최소 코스트


 근데 이걸 전처리하기 너무 귀찮다. 일단 더럽게 배열이 6차원이다. 


이 전처리를 줄일 수 있는데 s1, s2, s3, t1, t2, t3 정보가 모두 필요하지 않다는 데 핵심 아이디어가 있다. 실제로 필요한 정보는 (t1 -s1), (t2 - s2), (t3- s3) 정보다. 따라서 전처리 해야하는 내용을  


 pre[s1][s2][s3]  원래 다이얼로 부터 차이 값이 s1, s2, s3일 때 변환하기 위한 최소 코스트 

로 정의 할 수 있다. 물론 구현의 편의상 (-1 == 9) (-2 == 8) ... 이다. 따라서 s1, s2, s3 는 모두 0에서부터 9사이의 값을 가진다. 


dp 점화식 :



여기서 

n2 == 원래 다이얼의 n번째 숫자 

t0 == 목표 다이얼의 n-2번째 숫자

cost((s0,s1,s2) ->(t0,t1,t2)) 는 pre[t0-s0][t1-s1][t2-s2]이다.


디피 테이블 하나를 체우는데 10^2이 들고 모든 테이블을 체우기 위해서는 n*10^2이 드므로 시간복잡도는 n* 10^4 




상당히 많이 틀렸던 문제. 


이문제를 처음 틀리고 나는 완벽한데 틀렸다며 부들부들했던 문제다.


실수할 여지가 좀 많다.

완전 알고리즘을 못하던 시절에 손댔다가 실패했던 문젠데 생각이 나서 풀고 해설을 써본다.(실제로 BOJ 자물쇠에 대한 풀이를 원하시는 분들이 많다고 들었다)


소스코드는... 더럽다. 알아서 읽어보세여 ^ㅇ^ (심지어 변수명도 다름)


소스보기


+ Recent posts