제45회 SQLD 시험 후기

2022년 05월 28일 (토)에 시행된 제45회 SQLD 시험을 보고 왔다.

사실 44회 시험을 보려고 했는데 접수일자를 놓쳐서 45회를 봤다ㅎㅎ

코테에서도 SQL문제가 나오는 경우가 있는데, 코테 대비 겸 SQL기본기를 잡아보고자 자격증을 따기로 마음먹었다.

 

1. 공부기간

공부기간은 대략 7~10일 정도로 짧았고,

평일에는 퇴근 후 SQLD 이론 요약된 PDF를 가볍게 읽었다.

시험 일주일 전부터는 요약본 + 노랭이(SQL 자격검정 실전문제)를 풀었으며, 틀린 문제는 오답노트를 작성해 문제에 대한 개념과 오답인 이유를 정리했다.

시험 2일 전부터는 SQLD 복원된 기출문제를 풀면서 부족한 부분을 채워나갔다.

노랭이 풀면서 개념 정리 및 오답

 

2. 시험후기

사실 노랭이 풀면서 은근히 헷갈리는 것도 많고, 모르는 것도 있어서 걱정했는데 노랭이보다는 쉽게 나오는 것 같다.

시험 전날에 노랭이 + 기출문제 틀린 부분을 위주로 정리했는데

당일 시험에서 비슷한 문제/똑같은 문제가 꽤 보여서 놀랬다.

SQLD 시험 준비하면서 나름 개념들을 정리할 수 있는 시간이었던 것 같다!

 

# 22.06.19 추가

22.06.17 (금)에 시험 사전점수가 공개되었다는 문자를 받았다.

데이터 자격검정 페이지에 들어가 보니 시험 점수와 함께 합격 예정을 확인할 수 있었다!

자격증은 결과발표일(22.06.24) 10시 이후부터 출력할 수 있다고 한다.

 

 

3. 참고

 

데이터 전문가 포럼 (빅데이터분석기사... : 네이버 카페

빅데이터분석기사, ADP, ADsP, SQLP, SQLD, DAP, DAsP, 자격증 취득 등 데이터 전문가 커뮤니티입니다.

cafe.naver.com

SQLD, SQLP 등 데이터 관련 자료가 많이 공유되어있어 자격증 공부하는데 많은 도움이 되었다.

또한 노랭이를 풀다가 이해가 안 되는 부분은 이 카페를 참고했다.

카페에 복원된 기출문제도 있어서 풀어보면 많은 도움이 될 것 같다.

 

1918번: 후위 표기식

첫째 줄에 중위 표기식이 주어진다. 단 이 수식의 피연산자는 알파벳 대문자로 이루어지며 수식에서 한 번씩만 등장한다. 그리고 -A+B와 같이 -가 가장 앞에 오거나 AB와 같이 *가 생략되는 등의

www.acmicpc.net

 

풀이 방법

연산자에 우선순위를 부여하여 HashMap에 저장해 연산자 비교를 쉽게 할 수 있도록 했습니다.

 

만약 숫자라면 출력하고,

연산자라면 스택에 있는 연산자와 비교하여 우선순위를 이용해 스택에 저장할지 아님 출력할지를 결정했습니다.

 

또한 ')'인 경우에는 반복문을 돌면서 '('가 나올 때까지 출력했습니다.

그리고 for문이 끝난 뒤에는 stack에 저장된 값이 있다면 stack이 빌 때까지 출력해주었습니다.

 

 

코드

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Stack;
 
public class Main_BJ_1918_후위표기식 {
    
    static HashMap<Character, Integer> hm = new HashMap<>(); 
 
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        
        StringBuilder sb = new StringBuilder();
        
        Stack<Character> stack = new Stack<>();
        
        hm.put('*'3); hm.put('/'3);
        hm.put('+'2); hm.put('-'2);
        hm.put('('1); hm.put(')'1);
        
        String line = br.readLine();
        for(int i=0;i<line.length();i++) {
            char c = line.charAt(i);
            if(c=='(') stack.push(c);
            else if(c>=65 && c<=90) sb.append(c);
            else if(c=='+' || c=='-' || c=='*' || c=='/') {
                while(!stack.isEmpty()) {
                    if(priority(c)<=priority(stack.peek())) {
                        sb.append(stack.pop());
                    }else break;
                }
                stack.push(c);
            }else if(c==')') {
                while(!stack.isEmpty()) {
                    char top = stack.pop();
                    if(top=='('break;
                    else sb.append(top);
                }
            }
        }
        
        while(!stack.isEmpty()) sb.append(stack.pop());
        
        System.out.println(sb.toString());
    }

    public static int priority(char key) {
        return hm.get(key);
    }
 
}
 
cs

 

이펙티브 자바를 공부하면서 플라이웨이트 패턴이 나와 개념 정리 및 실습을 해보려고 한다.

 

1. 플라이웨이트 패턴(Flyweight Pattern)이란?


동일하거나 유사한 객체들 사이에 가능한 많은 데이터를 서로 공유하여 사용하도록 하여 메모리 사용량을 최소화하는 디자인 패턴이다.

즉, 자주 변하는 속성과 변하지 않는 속성을 분리하고, 변하지 않는 속성은 재사용하여 메모리 사용을 줄이는 방식이다.

 

 

2. Flyweight Pattern의 구성


  • Flyweight : 공유에 사용할 클래스
  • FlyweightFactory : Flyweight 인스턴스를 생성 또는 공유
  • Client : Flyweight : 해당 패턴의 사용자

 

3. 실습


  • Shape (공유에 사용할 클래스들의 인터페이스)
public interface Shape {
	public void draw();
}

 

  • Circle (인터페이스 내용 및 필요한 속성 정의)
public class Circle implements Shape {
	
	private String color;
	private int x;
	private int y;
	private int radius;
	
	public Circle(String color) {
		this.color = color;
	}

	public void setColor(String color) {
		this.color = color;
	}

	public void setX(int x) {
		this.x = x;
	}


	public void setY(int y) {
		this.y = y;
	}

	public void setRadius(int radius) {
		this.radius = radius;
	}

	@Override
	public void draw() {
		System.out.println("Circle [color= " + color +" , x= "+ x + " , y= "+ y +" , radius= "+ radius + " ]" );
	}
}

 

  • ShapeFactory (객체의 생성 또는 공유의 역할)
import java.util.HashMap;

public class ShapeFactory {
	public static final HashMap<String, Circle> circleMap = new HashMap<>();
	
	public static Shape getCircle(String color) {
		Circle circle = circleMap.get(color);
		
		if(circle == null) {
			circle = new Circle(color);
			circleMap.put(color, circle);
			System.out.println("---- 새로운 객체 생성 " + color +"색 원 ----" );
		}
		return circle;
	}
}

 

  • Main 클래스
public class Main {

	public static void main(String[] args) {
		String[] colors = {"Red", "Yellow", "Pink", "Blue"};
		
		for(int i=0;i<10;i++) {
			Circle circle = (Circle) ShapeFactory.getCircle(colors[(int) (Math.random()*4)]);
			circle.setX((int) (Math.random()*10));
			circle.setY((int) (Math.random()*20));
			circle.setRadius((int) (Math.random()*10));
			circle.draw();
		}
	}
}

 

  • 실행결과
---- 새로운 객체 생성 Blue색  ----
Circle [color= Blue , x= 8 , y= 5 , radius= 0 ]
---- 새로운 객체 생성 Red색  ----
Circle [color= Red , x= 5 , y= 5 , radius= 5 ]
---- 새로운 객체 생성 Pink색  ----
Circle [color= Pink , x= 6 , y= 17 , radius= 4 ]
Circle [color= Blue , x= 0 , y= 1 , radius= 6 ]
---- 새로운 객체 생성 Yellow색  ----
Circle [color= Yellow , x= 7 , y= 1 , radius= 4 ]
Circle [color= Yellow , x= 1 , y= 2 , radius= 0 ]
Circle [color= Red , x= 0 , y= 13 , radius= 3 ]
Circle [color= Yellow , x= 9 , y= 5 , radius= 1 ]
Circle [color= Pink , x= 1 , y= 16 , radius= 0 ]
Circle [color= Red , x= 7 , y= 11 , radius= 2 ]

같은 색상의 원은 1개만 생성되며, 생성된 객체를 공유하는 것을 확인할 수 있다.

 

 

4. 결론


4.1 언제 플라이웨이트 패턴을 사용하면 좋을까?

  • 공통적인 인스턴스를 많이 생성하는 로직이 포함된 경우
  • 자주 변하지 않는 속성을 재사용하는 경우

 

4.2 싱클톤 패턴과의 차이는 뭘까?

  • 싱클톤 패턴은 클래스 자체가 오직 1개의 인스턴스만 허용
  • 플라이웨이트 패턴은 싱글톤이 아닌 클래스 팩토리에서 제어

--> 인스턴스 생성의 제한을 어디서 제어하느냐의 차이

 

4.3 어디에서 플라이웨이트 패턴을 사용할까?

  • 임베디드와 같이 메모리를 최소한으로 사용해야 하는 경우에 활용
  • 클래스의 객체를 많이 만들어야할 때 사용

 

 

 

## 참고한 블로그 ##

 

[디자인패턴/Design Pattern] Flyweight Pattern / 플라이웨이트 패턴

관련 내용은 [자바 언어로 배우는 디자인 패턴 입문] , [Head First Design Pattern] 의 내용을 참고해서 정리한 글입니다. 잘못된 부분은 댓글로 피드백 부탁드립니다. 1. Flyweight 패턴이란? 어떤 클래스

lee1535.tistory.com

 

[구조 패턴] 플라이웨이트 패턴

1. 플라이웨이트 패턴(Flyweight Pattern)이란? 객체를 가볍게 만들어 메모리 사용을 줄이는 패턴 공통으로 사용하는 클래스(Flyweight)를 생성하는 팩토리 클래스(FlyweightFactory)를 만들어, 인스턴스를 최

dev-youngjun.tistory.com

 

'정리 > Design Pattern' 카테고리의 다른 글

Visitor Pattern - 방문자 패턴  (0) 2022.01.04
 
 

1. Visitor Pattern 이란?
2. Visitor Pattern의 적용 예시

 

1️⃣ Visitor Pattern

  • 방문자와 방문 공간을 분리하여, 방문 공간이 방문자를 맞이할 때, 이후에 대한 행동을 방문자에게 위임하는 패턴
  • 알고리즘을 객체 구조에서 분리시키는 디자인 패턴
    ⇒ 개방-폐쇄 원칙을 적용하는 방법 중 하나
    ⇒ 구조를 수정하지 않고도 실질적으로 새로운 동작을 기존의 객체 구조에 추가할 수 있게 된다.

 

예시

  • 쇼핑몰 고객을 등급별로 나누고 등급에 따라 혜택을 주기로 한다.
  • 등급은 Gold, Vip가 있고 혜택은 포인트, 할인이 있다.
  • 고객 등급별 혜택을 줄 수 있는 확장 가능한 해결책을 찾아보자.

 

public interface Member { }

public class GoldMember implements Member { }

public class VipMember implements Member { }

  • Member 인터페이스를 사용해서 등급별로 구체 클래스 생성

 

public class GoldMember implements Member {
	public void point() { System.out.println("Point for Gold Member"); }
	public void discount() { System.out.println("Discount for Gold Member"); }
}

public class VipMember implements Member {
	public void point() { System.out.println("Point for Vip Member"); }
	public void discount() { System.out.println("Discount for Vip Member"); }
}
  • 등급별 혜택 구현

 

public class Main {
	public static void main(String[] args) {
		Member gold = new GoldMember();
		Member vip = new VipMember();

		gold.point();
		vip.point();
		gold.discount();
		vip.discount();
	}
}
//실행 결과
Point for Gold Member
Point for Vip Member
Discount for Gold Member
Discount for Vip Member

 

 

⭐ 문제점 ⭐

  • 고객들에게 혜택을 주고자 할 때 명시적으로 혜택을 주기 위한 메소드를 호출해야한다.
  • 혜택이 늘어났을 경우 모든 멤버들에 대해 그 혜택을 구현했다는 보장이 없다.

 

 

⭐ 해결방안 ⭐

public interface Benefit {
    void getBenefit(GoldMember member);
    void getBenefit(VipMember member);
}
  • Benefit 인터페이스에 혜택을 받을 Member 별로 실행 가능한 메소드 정의

 

public class DiscountBenefit implements Benefit {
    @Override
    public void getBenefit(GoldMember member) {
        System.out.println("Discount for Gold Member");
    }

    @Override
    public void getBenefit(VipMember member) {
        System.out.println("Discount for Vip Member");
    }
}

public class PointBenefit implements Benefit {
    @Override
    public void getBenefit(GoldMember member) {
        System.out.println("Point for Gold Member");
    }

    @Override
    public void getBenefit(VipMember member) {
        System.out.println("Point for Vip Member");
    }
}
  • 멤버 등급별 혜택에 대해 기능 구현

 

public interface Member {
    void getBenefit(Benefit benefit);
}
  • 등급별 멤버가 혜택을 받을 수 있는 메소드를 Member 인터페이스에 선언

 

public class GoldMember implements Member {
    @Override
    public void getBenefit(Benefit benefit) {
        benefit.getBenefit(this);
    }
}

public class VipMember implements Member {
    @Override
    public void getBenefit(Benefit benefit) {
        benefit.getBenefit(this);
    }
}
  • 혜택받는 메소드 구현
  • 다른 Member가 추가되더라도 구현 부분은 benefit.getBenefit(Benefit benefit); 만 넣으면 된다.

 

public class Main {
    public static void main(String[] args) {
        Member goldMember = new GoldMember();
        Member vipMember = new VipMember();
        Benefit pointBenefit = new PointBenefit();
        Benefit discountBenefit = new DiscountBenefit();

        goldMember.getBenefit(pointBenefit);
        vipMember.getBenefit(pointBenefit);
        goldMember.getBenefit(discountBenefit);
        vipMember.getBenefit(discountBenefit);
    }
}

//실행 결과
Point for Gold Member
Point for Vip Member
Discount for Gold Member
Discount for Vip Member

 

⭐ 결과 ⭐

  • Visitor 패턴에서는 혜택이 늘어나더라도 Benefit 인터페이스에 명시적으로 등급별 메소드를 정의하고 있어 구현 누락이 발생하지 않는다.
  • 혜택을 추가하기 위해서 해당 혜택을 구현하는 클래스를 추가하면 되므로, 코드 중복이 발생하지 않는다.

 

⭐ Visitor 패턴을 언제 쓰면 좋을까? ⭐

  • 대상 객체가 잘 바뀌지 않고, 적용할 알고리즘이 추가될 가능성이 많은 상황일 때

 

 

참고

https://thecodinglog.github.io/design/2019/10/29/visitor-pattern.html

https://velog.io/@cham/Design-Pattern-방문자-패턴-Visitor-pattern

'정리 > Design Pattern' 카테고리의 다른 글

Flyweight Pattern - 플라이웨이트 패턴  (0) 2022.03.31
 

16469번: 소년 점프

첫째 줄에 미로의 행과 열의 크기를 나타내는 자연수 R과 C가 주어진다. (2 ≤ R, C ≤ 100) 다음 R줄에 걸 쳐 길이 C로 이루어진 각 줄의 미로의 정보가 공백 없이 주어진다. 숫자 0은 이동 가능한

www.acmicpc.net

 

풀이 방법

세명의 위치가 주어질 때 한 지점에 세명이 모일 때의 최소가 되는 시간을 구하는 문제였습니다.

 

저는 세명의 정보를 큐에 넣어두고 상 하 좌 우로 움직이면서 방문하지 않은 곳이라면 map배열의 값을 하나 올려주었습니다. 해당 위치의 값이 3일 경우에는 세명 모두 해당 위치를 방문했으므로 time 배열에 해당 시간을 넣어주었습니다. 그리고 find() 메서드에서 가장 최소 시간을 찾고 그러한 지점의 개수를 함께 출력해주었습니다.

 

⭐100%에서 틀렸습니다가 나오신다면.. 반례로

2 2
00
00
1 1
1 2
2 2

넣어보세요! ㅎㅎ ⭐

 

코드

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
import java.io.BufferedReader;
import java.io.IOException;
 
public class Main {
    
    static class info{
        int x,y,time;
        boolean [][] visited;
        public info(int x, int y, int time, boolean[][] visited) {
            super();
            this.x = x;
            this.y = y;
            this.time = time;
            this.visited = visited;
        }
    }
    
    static int [][] map, time;
    static int [] dx = {-1,0,1,0};
    static int [] dy = {0,1,0,-1};
    
    static int R,C;
    static Queue<info> queue = new LinkedList<>();
 
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        
        st = new StringTokenizer(br.readLine());
        
        R = Integer.parseInt(st.nextToken());
        C = Integer.parseInt(st.nextToken());
        
        map = new int[R][C];
        time = new int[R][C];
        
        for(int i=0;i<R;i++) {
            String line = br.readLine();
            for(int j=0;j<C;j++) {
                map[i][j] = line.charAt(j)-48;
                if(map[i][j]==1) map[i][j] = -1;
            }
        }
        
        for(int i=0;i<3;i++) {
            st = new StringTokenizer(br.readLine());
            int x = Integer.parseInt(st.nextToken())-1;
            int y = Integer.parseInt(st.nextToken())-1;
            
            queue.add(new info(x,y,0,new boolean[R][C]));
            map[x][y] = 1;
        }
        
        bfs();
        find();
    }
    
    public static void bfs() {
        
        
        while(!queue.isEmpty()) {
            info temp = queue.poll();
            temp.visited[temp.x][temp.y] = true;
            
            for(int i=0;i<4;i++) {
                int nx = temp.x+dx[i];
                int ny = temp.y+dy[i];
                
                if(range(nx,ny) && map[nx][ny]!=-1 && !temp.visited[nx][ny]) {
                    temp.visited[nx][ny] = true;
                    map[nx][ny]++;
                    queue.add(new info(nx,ny,temp.time+1,temp.visited));
                    
                    if(map[nx][ny]==3) time[nx][ny] = temp.time+1;
                }                
            }
        }
    }
    
    public static boolean range(int x ,int y) {
        return x>=0 && x<&& y>=0 && y<C;
    }
    
    public static void find() {
        int min = Integer.MAX_VALUE, count=0;
        for(int i=0;i<R;i++) {
            for(int j=0;j<C;j++) {
                if(time[i][j]!=0 && min>time[i][j]) {
                    min = time[i][j];
                    count=1;
                }
                
                else if(min==time[i][j]) count++;
            }
        }
        
        if(min==Integer.MAX_VALUE) System.out.println("-1");
        else {
            System.out.println(min+"\n"+count);
        }
    }
}
cs

 

 

21608번: 상어 초등학교

상어 초등학교에는 교실이 하나 있고, 교실은 N×N 크기의 격자로 나타낼 수 있다. 학교에 다니는 학생의 수는 N2명이다. 오늘은 모든 학생의 자리를 정하는 날이다. 학생은 1번부터 N2번까지 번호

www.acmicpc.net

 

풀이 방법

학생의 자리를 정하는데 다음과 같은 규칙이 존재합니다.

  1. 비어있는 칸 중에서 좋아하는 학생이 인접한 칸에 가장 많은 칸으로 자리를 정한다.
  2. 1을 만족하는 칸이 여러 개이면, 인접한 칸 중에서 비어있는 칸이 가장 많은 칸으로 자리를 정한다.
  3. 2를 만족하는 칸도 여러 개인 경우에는 행의 번호가 가장 작은 칸으로, 그러한 칸도 여러 개이면 열의 번호가 가장 작은 칸으로 자리를 정한다.

해당 학생이 좋아하는 학생의 번호를 저장하기 위해서 배열 안에 List를 넣어주었습니다.

해당 조건에 맞는 학생의 자리를 찾기위해 like와 empty배열을 사용하여 좋아하는 학생이 얼마나 인접해있는지와 비어있는 칸은 몇 개인지를 확인해 배열에 저장해주었습니다. 배열에 저장된 데이터를 기준으로 조건 1,2,3을 충족하는 경우에 해당 학생 자리를 배치해주는 방식으로 구현했습니다.

 

코드

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
 
public class Main_BJ_21608_상어초등학교 {
    
    static int N, answer=0;
    static int [][] seat, like, empty;
    static List<Integer> list[];
    static List<int []> condition1, condition2;
    
    static int [] dx = {-1,0,1,0};
    static int [] dy = {0,1,0,-1};
    static int [] score = {0,1,10,100,1000};
 
    public static void main(String[] args) throws NumberFormatException, IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        
        
        N = Integer.parseInt(br.readLine());
        
        seat = new int[N][N];
        
        list = new ArrayList[N*N+1];
        
        for(int i=1;i<N*N+1;i++) list[i] = new ArrayList<>();
        
        for(int i=0;i<N*N;i++) {
            st = new StringTokenizer(br.readLine());
            int student = Integer.parseInt(st.nextToken());
            for(int j=0;j<4;j++) {
                list[student].add(Integer.parseInt(st.nextToken()));
            }
            findSeat(student);
        }
        
        cal();
        System.out.println(answer);
 
    }
    
    
    public static void findSeat(int student) {
        like = new int[N][N];
        empty = new int[N][N];
        condition1 = new ArrayList<>();
        condition2 = new ArrayList<>();
        
        for(int i=0;i<N;i++) {
            for(int j=0;j<N;j++) {
                if(seat[i][j]==0) {
                    for(int d=0;d<4;d++) {
                        int nx = i+dx[d];
                        int ny = j+dy[d];
                        if(range(nx,ny)) {
                            if(list[student].contains(seat[nx][ny])) { //인접한 좋아하는 학생
                                like[i][j]++;
                            }
                            else if(seat[nx][ny]==0) { //인접한 빈 곳
                                empty[i][j]++;
                            }
                        }
                    }
                }
            }
        }
        
        int max=0;
        for(int i=0;i<N;i++) {
            for(int j=0;j<N;j++) {
                if(seat[i][j]==0) {
                    if(max<like[i][j]) {
                        max = like[i][j];
                        condition1.clear();
                        condition1.add(new int[] {i,j});
                    }else if(max==like[i][j]) {
                        condition1.add(new int[] {i,j});
                    }
                }
            }
        }
       //condition1 리스트 사이즈가 1인경우 조건1충족
        if(condition1.size()==1) seat[condition1.get(0)[0]][condition1.get(0)[1]] = student;
        else { //아닌 경우 조건 2,3고려
            max =0;
            for(int i=0;i<condition1.size();i++) {
                int [] temp = condition1.get(i);
                
                if(max<empty[temp[0]][temp[1]]) {
                    max = empty[temp[0]][temp[1]];
                    condition2.clear();
                    condition2.add(new int[] {temp[0],temp[1]});
                }else if(max==empty[temp[0]][temp[1]]) {
                    condition2.add(new int[] {temp[0],temp[1]});
                }
            }
            seat[condition2.get(0)[0]][condition2.get(0)[1]]= student;    
        }
        
    }
    
    public static boolean range(int x, int y) {
        return x>=0 && x<&& y>=0 && y<N;
    }
 
    public static void cal() {
        int count=0;
        for(int i=0;i<N;i++) {
            for(int j=0;j<N;j++) {
                count=0;
                for(int d=0;d<4;d++) {
                    int nx = i+dx[d];
                    int ny = j+dy[d];
                    
                    if(range(nx,ny) && list[seat[i][j]].contains(seat[nx][ny])) count++;
                }
                answer+=score[count];
            }
        }
    }
}
cs

 

 

 

17143번: 낚시왕

낚시왕이 상어 낚시를 하는 곳은 크기가 R×C인 격자판으로 나타낼 수 있다. 격자판의 각 칸은 (r, c)로 나타낼 수 있다. r은 행, c는 열이고, (R, C)는 아래 그림에서 가장 오른쪽 아래에 있는 칸이다.

www.acmicpc.net

 

풀이 방법

이 낚시왕 문제는 다시 풀어본 문제라 확실히 전보다는 코드가 더 깔끔해진 것 같습니다!

 

먼저,

1. 사람을 오른쪽으로 한 칸 움직인 뒤, 땅과 가장 가까운 상어를 하나 잡기

2. 격자판에 있는 상어를 움직이기

로 풀면 되는 시뮬레이션 문제였습니다.

 

저는 객체 배열을 하나 생성해 해당 위치에 상어의 정보를 넣어주었습니다. 상어가 움직일 때는 새로운 배열에 저장해 놓고 다 움직이고 난 뒤, 원래 배열에 복사해 넣는 방식으로 구현했습니다.

(상어 움직이는 것을 for문이 아닌 mod로 한다면 더 빨라질 것 같습니다!)

 

 

<예전 풀이>

 

백준 17143번 낚시왕 [JAVA]

문제 낚시왕이 상어 낚시를 하는 곳은 크기가 R×C인 격자판으로 나타낼 수 있다. 격자판의 각 칸은 (r, c)로 나타낼 수 있다. r은 행, c는 열이고, (R, C)는 아래 그림에서 가장 오른쪽 아래에 있는 칸

javaju.tistory.com

 

 

코드

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
 
public class Main_BJ_17143_낚시왕 {
    
    static class shark {
        int s,d,z;
 
        public shark(int s, int d, int z) {
            super();
            this.s = s;
            this.d = d;
            this.z = z;
        }
        
    }
    
    static int R,C,M, answer=0;
    static shark [][] map, copy;
    static int [] dx = {0,-1,1,0,0};
    static int [] dy = {0,0,0,1,-1};
 
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        
        st = new StringTokenizer(br.readLine());
        
        R = Integer.parseInt(st.nextToken());
        C = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken()); //상어 수
        
        map = new shark[R][C];
        
        for(int i=0;i<M;i++) {
            st = new StringTokenizer(br.readLine());
            
            int r = Integer.parseInt(st.nextToken())-1
            int c = Integer.parseInt(st.nextToken())-1;
            int s = Integer.parseInt(st.nextToken()); //속력
            int d = Integer.parseInt(st.nextToken()); //이동 방향
            int z = Integer.parseInt(st.nextToken()); //크기
            
            map[r][c] = new shark(s,d,z);
        }
        
        for(int i=0;i<C;i++) {
            //1.한칸 이동해서 땅과 가장 가까운 상어 잡아먹기
            movePerson(i);
            
            //2.상어 이동하기
            moveShark();
        }
        
        System.out.println(answer);
    }
    
    public static void movePerson(int y) {
        for(int i=0;i<R;i++) {
            if(map[i][y]!=null) {
                answer+=map[i][y].z;
                map[i][y]=null;
                return;
            }
        }
    }
    
    public static void moveShark() {
        copy = new shark[R][C];
        
        for(int i=0;i<R;i++) {
            for(int j=0;j<C;j++) {
                if(map[i][j]!=null) { //상어 움직이자!
                    shark temp = map[i][j];
                    map[i][j] = null;
                    
                    int nx=i,ny=j;
                    for(int k=0;k<temp.s;k++) {
                        if(temp.d==1 && nx==0) temp.d=2;
                        else if(temp.d==2 && nx==R-1) temp.d=1;
                        else if(temp.d==3 && ny==C-1) temp.d=4;
                        else if(temp.d==4 && ny==0) temp.d=3;
                        
                        nx+=dx[temp.d];
                        ny+=dy[temp.d];
                    }
                    
                    if(copy[nx][ny]==null || copy[nx][ny].z<temp.z ) {
                        copy[nx][ny] = temp;
                    }
                }
            }
        }
        map = copy;
    }
}
cs

 

 

 

13549번: 숨바꼭질 3

수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈이의 위치가 X일

www.acmicpc.net

 

풀이 방법

N의 위치에서 K위치까지 가는데 걸리는 최소의 시간을 구하는 문제였습니다.

 

저는 BFS알고리즘을 사용하여 문제를 풀었으며,

for문을 이용해 순간 이동할 때와 걸을 경우를 구분하여 우선순위 큐에 넣어주었습니다. 방문을 확인하는 visited배열을 이용하여 해당 이동한 곳이 방문한 곳이 아닐 경우에만 이동할 수 있도록 구현했습니다. 우선순위 큐로 움직인 횟수가 가장 작은 것부터 움직일 수 있도록 했기 때문에 만약 현재 위치가 동생이 있는 곳이라면 시간을 출력해주고 반복문을 종료해주었습니다. 

 

코드

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
 
public class Main_BJ_13549_숨바꼭질3 {
    
    static class info implements Comparable<info>{
        int position, time;
 
        public info(int position, int time) {
            super();
            this.position = position;
            this.time = time;
        }
 
        @Override
        public int compareTo(info o) {
            return this.time-o.time;
        }
    }
    
    static int N,K;
    static boolean [] visited;
 
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        
        st = new StringTokenizer(br.readLine());
 
        N = Integer.parseInt(st.nextToken());
        K = Integer.parseInt(st.nextToken());
 
        visited = new boolean[100001];
        
        move();
    }
    
    public static void move() {
        Queue<info> pq = new LinkedList<>();
        
        pq.add(new info(N,0));
        
        while(!pq.isEmpty()) {
            info temp = pq.poll();
            
            if(temp.position == K) {
                System.out.println(temp.time);
                return;
            }
            
            int nx = 0;
            for(int i=0;i<3;i++) {
                if(i==0) nx = temp.position*2;
                else if(i==1) nx = temp.position-1;
                else if(i==2) nx = temp.position+1;
                
                if(range(nx) && !visited[nx]) {
                    if(i==1 || i==2) pq.add(new info(nx, temp.time+1));
                    else pq.add(new info(nx, temp.time));
                    visited[nx] = true;
                }
            }
        }
    }
    
    public static boolean range(int x) {
        return x>=0 && x<visited.length;
    }
 
}
cs

 

 

 

3085번: 사탕 게임

예제 3의 경우 4번 행의 Y와 C를 바꾸면 사탕 네 개를 먹을 수 있다.

www.acmicpc.net

 

풀이 방법

배열 전체를 돌면서 기준이 되는 사탕과 인접한 사탕의 색깔이 다른 경우 위치를 교환해, 행과 열을 확인하여 최대 먹을 수 있는 사탕을 계산해 주었습니다.

 

 

코드

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
 
public class Main_BJ_3085_사탕게임 {
    
    static int [] dx = {-1,0,1,0};
    static int [] dy = {0,1,0,-1};
    
    static int N, max=0;
    static char [][] map;
    
    public static void main(String[] args) throws NumberFormatException, IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        
        N = Integer.parseInt(br.readLine());
        
        map = new char[N][N];
        
        for(int i=0;i<N;i++) {
            String line = br.readLine();
            for(int j=0;j<N;j++) {
                map[i][j] = line.charAt(j);
            }
        }
        
        candy();
        System.out.println(max);
    }
    
    public static void candy() {
        for(int x=0;x<N;x++) {
            for(int y=0;y<N;y++) {
                
                for(int d=0;d<4;d++) { // 상 하 좌 우 인접한곳
                    int nx = x + dx[d];
                    int ny = y + dy[d];
                    
                    if(range(nx,ny) && map[x][y]!=map[nx][ny]) {
                        char temp = map[x][y];
                        map[x][y] = map[nx][ny];
                        map[nx][ny] = temp;
                        
                        check(); //먹을 수 있는 사탕 개수 확인
                        
                        temp = map[x][y];
                        map[x][y] = map[nx][ny];
                        map[nx][ny] = temp;
                    }
                }
            }
        }
    }
    
    public static boolean range(int x, int y) {
        return x>=0 && x<&& y>=0 && y<N;
    }
    
    public static void check() {
        
        for(int i=0;i<N;i++) {
            for(int j=0;j<N;j++) {
                count(i,j);
            }
        }    
    }
    
    public static void count(int x, int y) {
        
        int yy=y, xx=x, row=1, col=1;
        //연속된 행
        for(int i=y+1;i<N;i++) {
            if(map[x][yy]==map[x][i]) {
                row++;
                yy = i; 
            }else break;
        }
        
        //연속된 
        for(int i=x+1;i<N;i++) {
            if(map[xx][y]==map[i][y]) {
                col++;
                xx = i;
            }else break;
        }
        
        int result = Math.max(row, col);
        max = Math.max(result, max);
    }
 
}
cs
 
 
 

 

 

11724번: 연결 요소의 개수

첫째 줄에 정점의 개수 N과 간선의 개수 M이 주어진다. (1 ≤ N ≤ 1,000, 0 ≤ M ≤ N×(N-1)/2) 둘째 줄부터 M개의 줄에 간선의 양 끝점 u와 v가 주어진다. (1 ≤ u, v ≤ N, u ≠ v) 같은 간선은 한 번만 주

www.acmicpc.net

 

풀이 과정

방향 없는 그래프가 주어졌을 때, 연결 요소의 개수를 구하는 문제였습니다.

 

저는 Union Find 알고리즘을 이용하여 문제를 풀었으며,

각각의 간선의 부모(Find)가 다른 경우 Union 메서드를 통해 간선을 연결시켜 주었습니다.

 

M번의 반복문이 끝난 뒤, HashSet을 이용해 연결요소의 개수를 구해주었습니다.

 

[같은 문제의 배열 풀이방법]

 

백준 11724번 연결 요소의 개수 [JAVA]

문제 방향 없는 그래프가 주어졌을 때, 연결 요소 (Connected Component)의 개수를 구하는 프로그램을 작성하시오. 입력 첫째 줄에 정점의 개수 N과 간선의 개수 M이 주어진다. (1 ≤ N ≤ 1,000, 0 ≤ M ≤ N

javaju.tistory.com

 

코드

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashSet;
import java.util.StringTokenizer;
 
public class Main_BJ_11724_연결요소의개수 {
    
    static int N,M;
    static int [] parents;
 
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        HashSet<Integer> hs = new HashSet<>();
        
        StringTokenizer st;
        
        st = new StringTokenizer(br.readLine());
        
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        
        parents = new int[N+1];
        
        for(int i=1;i<parents.length;i++) parents[i] = i;
        
        for(int i=0;i<M;i++) {
            st = new StringTokenizer(br.readLine());
            
            int u = Integer.parseInt(st.nextToken());
            int v = Integer.parseInt(st.nextToken());
            
            if(find(u)!=find(v)) union(u,v);
                
        }
        
        for(int i=1;i<parents.length;i++) {
            hs.add(find(parents[i]));
        }
        
        System.out.println(hs.size());
    }
    
    public static void union(int a,int b) {
        int aRoot = find(a);
        int bRoot = find(b);
        
        if(aRoot>bRoot) parents[aRoot] = bRoot;
        else parents[bRoot] = aRoot;
    }
    
    public static int find(int a) {
        if(parents[a]==a) return a;
        return parents[a] = find(parents[a]);
    }
 
}
cs

 

'문제 > 백준' 카테고리의 다른 글

백준 13549번 숨바꼭질3 [JAVA]  (0) 2021.11.23
백준 3085번 사탕 게임 [JAVA]  (0) 2021.11.18
백준 1753 최단경로 [JAVA]  (0) 2021.11.06
백준 15686 치킨 배달 [JAVA]  (0) 2021.10.23
백준 1406번 에디터 [JAVA]  (0) 2021.10.20

+ Recent posts