Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
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
Archives
Today
Total
관리 메뉴

시간이 NullNull

[JAVA] [SWEA] 3975. 승률 비교하기 본문

카테고리 없음

[JAVA] [SWEA] 3975. 승률 비교하기

4NIng 2019. 5. 13. 00:25

삼성 1:1 프로그래밍 리그의 시즌이 끝났다. 앨리스는 B전 A승, 밥은 D전 C승이다. 누구의 승률이 더 높은가?

 

이 문제의 경우 이게 왜 D3일까 고민할 정도로 너무 간단한 문제였다.

 

하지만 아무 생각없이 제출을 하지 시간초과가 떴었고 이후 내 쓰는 라이브러리가 바뀌게 되는 결과가 나왔다.

 

중요 포인트는 자바의 경우 10만 개의 케이스를 실행시키는데 2초.

 

이것을 모른 채로 풀었었는데 한참뒤에 깨닫고 시간을 줄이는 방법을 생각해보았으나 로직에는 아무 문제가 없고

 

결국 입력과 출력의 방식에 차이가 있다는 것을 깨달았다.

 

맨 처음 내가 시도했던 코드이다.

 

import java.util.Scanner;
public class Solution {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int T = sc.nextInt();
		for(int p=1; p<=T; p++) {
			double A = sc.nextDouble();
			double B = sc.nextDouble();
			double C = sc.nextDouble();
			double D = sc.nextDouble();
			double alice = A/B;
			double bob = C/D;
			String result = "";
			if(alice == bob) result = "DRAW";
			else if( alice > bob) result = "ALICE";
			else result = "BOB";
			System.out.printf("#%d %s%n",p,result);
		}
	}
}

 

누가봐도 알아볼 수 있는 간단한 코드이지만 아쉽게도 시간초과가 난다.

 

결론적으로 여러가지 실험을 해보았는데 먼저 성공한 코드를 보여주겠다.

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Solution {
	public static void main(String[] args) throws Exception{
		// TODO Auto-generated method stub
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int T = Integer.parseInt(br.readLine());
		double A, B, C, D, alice, bob;
		for(int p=1; p<=T; p++) {
			String s = br.readLine();
			String[] arr = s.split(" ");
			A = Double.parseDouble(arr[0]);
			B = Double.parseDouble(arr[1]);
			C = Double.parseDouble(arr[2]);
			D = Double.parseDouble(arr[3]);
			alice = A/B;
			bob = C/D;
			String result = "BOB";
			if(alice == bob) {
				result = "DRAW";
			}else if( alice > bob) {
				result = "ALICE";
			}
			System.out.println("#"+p+" "+result);
		}
	}

}

 

출력의 경우 내가 이전에 쓰던 것 처럼 BufferedWriter를 쓰는 것이 더욱 효과적일 것이다.

 

BufferedReader와 Scanner도 속도 차이가 나는데

 

import java.util.Scanner;
public class Solution {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int T = sc.nextInt();
        for(int p=1; p<=T; p++) {
            double A = sc.nextDouble();
            double B = sc.nextDouble();
            double C = sc.nextDouble();
            double D = sc.nextDouble();
            double alice = A/B;
            double bob = C/D;
            String result = "";
            if(alice == bob) result = "DRAW";
            else if( alice > bob) result = "ALICE";
            else result = "BOB";
            System.out.println("#"+p+" "+result);
        }
    }
}

 

이 코드의 경우 시간초과가 난다.

 

결론적으로 주변에 물어보고 조금씩 검색하면서 깨달은 점은 적어도 printf는 쓰면 안되는 것이다.

 

printf 의 경우 포맷을 정해놓고 매칭을 시켜주는 것 때문에 시간이 println보다 더 오래 걸리게 되는데

 

println의 경우 괄호안에 있는 것(String)을 그냥 출력시키는 것이 전부이기 때문이다.

 

BufferedWriter의 경우 정확히는 모르지만 내가 알기로는 buffer 안에 다 써놓고

 

BufferedWriter가 클로즈 되는 지점에서 buffer에 써있던 것들이 다 출력되는 것으로 알고 있다.

 

따라서 println보다 더 출력하는 행위가 작기 때문에 조금 더 빠른 것으로 알고있다.

 

아는 형의 경우 StringBuilder나 StringBuffer를 사용하는 경우도 있으니 참고하여 본인이 가장 편한것을 쓰는 것을 추천한다.

 

결론 :

1. Scanner 보단 BufferedReader( StringTokenizer 를 함께 이용하여도 무관하다.)

2. 적어도 printf는 쓰지말자

3. 출력문을 빠르게 하고싶다면 BufferedWriter나 StringBuilder, StringBuffer와 같은 것을 활용해보자

Comments