2010 프로야구 BASEBALL 문제 질문합니다 ㅠ_ㅠ

  • Jubei
    Jubei

    코드는 다 짰고 테스트 케이스도 정상적으로 동작하는데
    메모리를 많이썼다고 SIGKILL 당했네요..
    이거 메모리를 어떻게 줄여야할까요 ㅠ_ㅠ..

    코드 간략하게 설명드리면, 각 팀의 승/무/패/승률 을 갖는 객체를 만들고, 그 객체 배열을 갖고 순위리턴, 잔여경기 결과반영 등의 동작을 수행하는 리그 객체가 있습니다.

    그리고 잔여 경기들에 따라 가능한 모든 경우의 수를 3진 포화트리로 구성했습니다. 그렇게 해서 트리를 순회하면서 leaf node 일때 해당 경기결과를 리그에 반영시켜서 순위를 산출하게 했습니다...

    ㅠㅠ..메모리 줄일 방법좀 도와주세요 ㅠ_ㅠ..아예 다시짜야하나요?

    import java.io.File;
    import java.io.FileNotFoundException;
    import java.util.Scanner;

    public class Main {

    public static void main(String[] args) throws FileNotFoundException {
    
        //Scanner sc = new Scanner(new File("input.txt"));
        Scanner sc = new Scanner(System.in);
        int cases = sc.nextInt();
    
        /*
         * 이 부분에 구현할 알고리즘을 작성할 것.
         * 변수 선언,활용 등은 자유롭게 가능.
         */
    
        for( int a=0; a<cases; a++ ) {
            League myLeague = new League();
            String MyTeam;  // 응원하는팀
            int remainGame;
            Tree myTree = new Tree();
    
            // 입력으로부터 8개팀 정보 입력받아서 리그 배열에 저장
            for( int b=0; b<8; b++ ) {
                String tn = sc.next();
                int w = sc.nextInt();
                int d = sc.nextInt();
                int l = sc.nextInt();
                TeamInfo tmp = new TeamInfo(tn,w,d,l);
    
                myLeague.LeagueArr[b] = tmp;
            }
    
            MyTeam = sc.next(); // 응원하는 팀 저장
            remainGame = sc.nextInt();  // 잔여경기 저장
    
            // 잔여경기에 따른 모든 경우의수를 나타내는 3진포화트리 만들기
            for( int b=0; b<remainGame; b++ ) {
                String str1 = sc.next();
                String str2 = sc.next();
                myTree.insert(str1,  str2, b);
            }
    
            myTree.Arr = myLeague;
            boolean ck = myTree.gogosing(MyTeam);
    
            if(ck)
                System.out.println("YES");
            else
                System.out.println("NO");
    
        }
    
        sc.close();
    
    }

    }

    class TeamInfo {
    public String teamName;
    public int winCount;
    public int drawCount;
    public int loseCount;
    public double winRate;

    public TeamInfo(String tn, int w, int d, int l) {
        teamName = tn;
        winCount = w;
        drawCount = d;
        loseCount = l;
        // 0승0무0패 들어오면 승률0으로셋팅
        if( (w+d+l)!= 0 ) winRate = w / (double)(w+d+l);
        else winRate = 0;
    }
    
    public TeamInfo() {
        teamName = null;
        winCount = 0;
        drawCount = 0;
        loseCount = 0;
        winRate = 0;
    }
    
    // 승률갱신메소드
    public void setWinRate() {
        if( (winCount+drawCount+loseCount)!= 0 ) winRate = winCount / (double)(winCount+drawCount+loseCount);
        else winRate = 0;
    }

    }

    class League {
    public TeamInfo[] LeagueArr;

    public League() {
        LeagueArr = new TeamInfo[8];
    }
    
    public League(TeamInfo[] ti) {
        LeagueArr = ti;
    }
    // 팀이름으로 해당팀 객체 반환하는 메소드
    public TeamInfo getTeamObj(String teamname) {
        for( int i=0; i<8; i++ ) {
            if( LeagueArr[i].teamName.equals(teamname) )
                return LeagueArr[i];
        }
        return null;
    }
    
    // 팀이름으로 해당팀 순위 반환하는 메소드
    public int getTeamRank(String teamname) {
        double tmp=0;
        int rank=1;
        // 팀이름으로 해당팀 승률 가져옴
        for( int i=0; i<8; i++ ) {
            if( LeagueArr[i].teamName.equals(teamname) )
                tmp = LeagueArr[i].winRate;             
        }
        // 순위 확인
        for( int i=0; i<8; i++ ) {
            if( LeagueArr[i].winRate > tmp )
                rank++;
        }
        return rank;
    }
    
    // 경기결과 반영 메소드. b=true면 승패갈림. b=false면 무승부
    public void setGameResult(String winTeam, String loseTeam, boolean b ) {
        TeamInfo wt = getTeamObj(winTeam);
        TeamInfo lt = getTeamObj(loseTeam);
    
        if(b) {
            wt.winCount++;
            lt.loseCount++;
        }
        else {
            wt.drawCount++;
            lt.drawCount++;
        }
        wt.setWinRate();
        lt.setWinRate();
    }

    }

    // 트리 노드 클래스
    class Node {
    public String name;
    public Node parentNode;
    public Node leftNode;
    public Node centerNode;
    public Node rightNode;

    public Node(String tn, Node parent, Node left, Node right) {
        name = tn;
        parentNode = parent;
        leftNode = left;
        rightNode = right;
        centerNode = null;
    }
    
    public Node() {
        name = null;
        parentNode = null;
        leftNode = null;
        rightNode = null;
        centerNode = null;
    }
    
    public Node(String tn) {
        name = tn;
        parentNode = null;
        leftNode = null;
        rightNode = null;
        centerNode = null;
    }
    
    public boolean isLeaf() {
        if( leftNode==null && rightNode==null ) return true;
        else return false;
    }
    
    public void setParent(Node n) {
        this.parentNode = n;
    }

    }

    // 트리 클래스
    class Tree {
    public Node rootNode;
    public boolean ck;
    public League Arr;
    public League ArrCopy;

    public Tree() {
        rootNode = new Node("root");
        ck = false;
    }
    
    // 트리 전체를 순환하면서 리프노드일때 node1, node2, 무승부노드 를 달아준다.
    // 3진포화트리가 되는거임.
    public void insertNode(Node p, String s1, String s2, int num) {
    
        if( p==null ) return;
    
        //System.out.println("   !!!! 노드 " + p.name + " 방문 !!!!");
        //System.out.println(p.name + " 방문!");
        // 리프노드면 num이랑 노드의 depth랑 값 같을때 노드 달아줌
        if( p.isLeaf() ) {
            Node node1 = new Node(s1);
            Node node2 = new Node(s2);
    
            //Node tmp = p;
            //int depth = 0;
            /*
            while(tmp!=rootNode) {
                tmp = tmp.parentNode;
                depth++;
            }
            */
            //if( depth==num ) {
                //System.out.println("          리프노드 " + p.name + "방문! 현재 depth,num은 " + depth + "," + num);
                node1.setParent(p);
                node2.setParent(p);
                Node n = new Node("draw");
                n.setParent(p);
    
                p.leftNode = node1;
                p.rightNode = node2;
                p.centerNode = n;
                /*
                if( num==0)
                    System.out.println("num : " + num + "이고, Node:[ " + p.name + " ]에다가 [ " + node1.name + " ] 랑 [ " + node2.name + " ]를 달았음.");
                else if( num!=0 )
                    System.out.println("num : " + num + "이고, 부모가 [ " + p.parentNode.name + " ]인 Node:[ " + p.name + " ]에다가 [ " + node1.name + " ] 랑 [ " + node2.name + " ]를 달았음.");
                */
            //}
            return;
        }
        insertNode(p.leftNode, s1, s2, num);
        insertNode(p.centerNode, s1, s2, num);
        insertNode(p.rightNode, s1, s2, num);
    }
    
    public void insert(String s1, String s2, int num) {
        insertNode(rootNode, s1, s2, num);
    }
    
    
    
    // 팀정보 배열 받고 트리가지고 모든결과 반영해보면서 진출 가능한지 확인하는 메소드임
    public boolean gogosing(String myteam) {
        ArrCopy = new League(Arr.LeagueArr);
        realgogo(rootNode, ArrCopy, myteam);        
        return ck;
    }
    
    // 실제 알고리즘 동작하는 메소드. 3진포화트리를 재귀호출로 돌면서 리프노드이면 루트까지 가면서 경기결과반영.
    void realgogo(Node p, League lgarr, String myteam) {
    
        // 리프노드면, 루트까지 부모노드 타고 올라가면서 해당되는 경기결과를 갱신한다.
        if( p.isLeaf() ) {
            Node tmp = p;
    
            // 루트노드까지 부모타고가면서 정보갱신
            while(tmp!=rootNode) {
    
                // 무승부면 부모의 양옆 자식들 이름 가져와서 무승부 갱신
                if( tmp.name.equals("draw") ) {
                    String s1 = tmp.parentNode.leftNode.name;
                    String s2 = tmp.parentNode.rightNode.name;
                    lgarr.setGameResult(s1, s2, false);
                }
                // 무승부아니면 현재 tmp가 가르키는 노드가 승리한걸로 하면서 결과갱신
                else {
                    String wt;
                    String lt;
                    // tmp가 부모의 왼쪽노드일때
                    if( tmp.parentNode.leftNode.equals(tmp) ) {
                        wt = tmp.name;
                        lt = tmp.parentNode.rightNode.name;
                    }
                    // p가 부모의 오른쪽노드일때 (위에서 무승부 조건을 갈랐으므로 왼쪽아니면오른쪽임)
                    else {
                        wt = tmp.name;
                        lt = tmp.parentNode.leftNode.name;
                    }
                    lgarr.setGameResult(wt, lt, true);  // 결과갱신
                }
                tmp = tmp.parentNode;
            }
            // 리프노드 1개에서 결과 다 반영하면, myteam이 진출 가능한지 확인해준다.
            // 확인까지 다하고 나면, 리그결과 갱신했던걸 다시 원래대로 돌린다.
            int num = lgarr.getTeamRank(myteam);
            if( num<=4 ) {
                ck = true;
            }
            lgarr = new League(Arr.LeagueArr);
            return;
        }
    
        realgogo(p.leftNode,lgarr,myteam);
        realgogo(p.centerNode,lgarr,myteam);
        realgogo(p.rightNode,lgarr,myteam);
    
    }

    }


    9년 전
0개의 댓글이 있습니다.
  • 정회원 권한이 있어야 커멘트를 다실 수 있습니다. 정회원이 되시려면 온라인 저지에서 5문제 이상을 푸시고, 가입 후 7일 이상이 지나셔야 합니다. 현재 문제를 푸셨습니다.