코딩테스트/백준

[Dev-Ping9] 백준 14889번 - 스타트와 링크 (Java)

DevPing9_ 2021. 12. 30. 00:38

 

[1차 시도]

 

ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ 메모리가 터져나간다 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

공부를 좀 더해야겠다....😢

 

[2차 시도]

 

 

 

# 문제설명

 일단 문제 설명에 따라 nCn/2 의 경우를 탐색해야한다.

 탐색한 후, 각 경우에서 또 (n/2)! 만큼 탐색하면 되는 것 같다.

 

 그러나 나는 A팀에 1번이 포함됬을 경우,  [1][] , [][1] 을 모두 지워버리는 식으로

 A팀에 포함된 모두를 아래와 같이 지워버리고 B팀의 점수를 집계했다.

 

 그 결과 2308ms -> 1212ms 라는 좋지 않은 수행시간 점수를 받아버렸다...  

 

 

 

 

# 구현코드

 

1차 코드 (메모리 303,956KB / 시간 2308ms)

 - nCr 마구잡이로 짜보고, 2차원배열도 clone()을 통해 복사가 되는지 확인해보았다. (된다...!!!)

 - 통과한게 신기할정도로 처참한 성능

 - nCr 코드 같은건 어느정도 정형화 할 필요가 있음을 깨달았다. (그래도 nCr 은 나쁘지않게 짠 것 같다.)

 

더보기
더보기

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

public class Main{
    static int[][] stat;
    static boolean[] visited;
    static int optimal=Integer.MAX_VALUE;

    static void makeZero(int [][] arr, int idx){
        for(int i=1; i<arr.length; i++){
            arr[idx][i]=0;
            arr[i][idx]=0;
        }
    }

    static int getSum(int [][] arr){
        int sum=0;
        for(int i=1;i<arr.length;i++){
            for(int j=1;j<arr.length;j++){
                sum+=arr[i][j];
            }
        }
        return sum;
    }

    static int cal(int size){
        int a=0, b=0;
        int[][] aTeam = new int[size+1][size+1];
        int[][] bTeam = new int[size+1][size+1];
        
        for(int i=0; i<stat.length; i++){
            aTeam[i]= stat[i].clone();
            bTeam[i]= stat[i].clone();
        }


        for(int i=1; i<=size; i++){
            for(int j=1;j<=size; j++){
                if(visited[i]){ //a팀
                    makeZero(aTeam, i);
                }else{
                    makeZero(bTeam, i);
                }
            }
        }
        

        a = getSum(aTeam);
        b = getSum(bTeam);

        return Math.abs(a-b);
    }
    static void printArr(int n){
        for(int i=1; i<=n; i++){
            System.out.print(visited[i]+ " ");
        }
        System.out.println();
    }

    static void nCr(int start,int n,int r,int end){
        
        if(end == n/2){
            optimal = Math.min(cal(n),optimal);
            return;
        }
        if(start == n+1) return;
            
        visited[start]=true; //a Team
        nCr(start+1, n, r, end+1);
        visited[start]=false;
        nCr(start+1, n, r, end);
        
    }

    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        stat = new int[n+1][n+1];
        visited = new boolean[n+1];
        //init array
        for(int i =1; i<=n; i++){
            StringTokenizer st = new StringTokenizer(br.readLine()," ");
            for(int j=1; j<=n; j++){
                stat[i][j] = Integer.parseInt(st.nextToken());
            }
        }


        nCr(1, n, n/2, 0);
        System.out.println(optimal);
        
    }
}

 

 

2차 코드 (메모리 38,568KB / 시간 1212ms) - 메모리는 9할가량, 시간은 5할가량 줄였다..!

 - 탐색결과를 boolean 으로 나타내지않고, 숫자형태로 가져온다면 매핑시간이 줄어들 것에 착안 

 - for문의 시행횟수를 줄여보았다. (그래도 아직 부족한 것 같다. 3차 시도에는 접근 방식을 바꾸어야겠다.)

 

더보기
더보기
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

public class Main{
    static int[][] stat;
    static int cnt;
    static int optimal=Integer.MAX_VALUE;
    static List<Integer> aTeamList;
    static List<Integer> bTeamList;


    static boolean isContain(int i, List<Integer> list){
        for(int k=0;k<list.size();k++){
            if(i==list.get(k)){
                return true;
            }
        }
        return false;
    }

    static int cal(int size){
        int a=0, b=0;

        //b 팀 합산
        for(int i=1; i<=size; i++){
            if(isContain(i,aTeamList)) continue;
            for(int j=1;j<=size; j++){
                if(isContain(j,aTeamList)) continue;
                else if(i==j) continue;
                b+=stat[i][j];
            }
        }
        
        // a 팀 합산
        for(int i=1; i<=size; i++){
            if(isContain(i,bTeamList)) continue;
            for(int j=1;j<=size; j++){
                if(isContain(j,bTeamList)) continue;
                else if(i==j) continue;
                a+=stat[i][j];
            }
        }

        return Math.abs(a-b);
    }

    static void nCr(int start,int n,int r,int end){
        
        if(end == n/2 && bTeamList.size()==n/2){
            
            optimal = Math.min(cal(n),optimal);
            return;
        }
        if(start == n+1) return;

            
        aTeamList.add(start); //aTeam
        nCr(start+1, n, r, end+1);
        aTeamList.remove((Integer)start);
        bTeamList.add(start);
        nCr(start+1, n, r, end);
        bTeamList.remove((Integer)start);
        
            
    }

    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        stat = new int[n+1][n+1];
        //init array
        for(int i =1; i<=n; i++){
            StringTokenizer st = new StringTokenizer(br.readLine()," ");
            for(int j=1; j<=n; j++){
                stat[i][j] = Integer.parseInt(st.nextToken());
            }
        }

        aTeamList= new ArrayList<>();
        bTeamList= new ArrayList<>();

        nCr(1, n, n/2, 0);
        System.out.println(optimal);
    }
}

 

 

728x90