반응형

문제링크 : https://www.acmicpc.net/problem/3108

 

3108번: 로고

문제 로고는 주로 교육용에 쓰이는 프로그래밍 언어이다. 로고의 가장 큰 특징은 거북이 로봇인데, 사용자는 이 거북이 로봇을 움직이는 명령을 입력해 화면에 도형을 그릴 수 있다. 거북이는 위치와 각도로 표현할 수 있다. 거북이는 입에 연필을 물고 있는데, 연필을 내리면 움직일 때 화면에 선을 그리고, 올리면 선을 그리지 않고 그냥 지나가기만 한다. 제일 처음에 거북이는 (0,0)에 있고, 거북이가 보고 있는 방향은 y축이 증가하는 방향이다. 또한 연필은 내

www.acmicpc.net

거북이는 같은 선을 여러 번 그릴 수 있다. 따라서 교차하는 직사각형들을 한 그룹으로 보고(교차할 경우, 한 번에 다 그릴 수 있으므로) 그룹의 개수를 구하면 되는 문제이다.

 

위 그림을 예로 들면, 교차하는 직사각형의 그룹이 총 3개이므로, 로고는 총 3번의 PU 명령어를 통해 모든 직사각형을 그릴 수 있다.

 

교차하는 직사각형의 그룹의 개수를 구하는 방법은, 각 직사각형들이 교차하는 지의 여부를 인접행렬에 저장해놨다가 DFS를 통해 개수를 구한다. 코드는 아래와 같다.

 

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
 
public class Main {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        Rectangle[] rectangles = new Rectangle[n];
        boolean[][] intersect = new boolean[n][n];
        boolean crossZero = false;
        
        for(int i = 0; i < n; i++) {
            StringTokenizer st = new StringTokenizer(br.readLine());
            int x1 = Integer.parseInt(st.nextToken());
            int y1 = Integer.parseInt(st.nextToken());
            int x2 = Integer.parseInt(st.nextToken());
            int y2 = Integer.parseInt(st.nextToken());
            
            rectangles[i] = new Rectangle(x1, y1, x2, y2);
            
            if(y1 == 0 && x1 * x2 <= 0 || y2 == 0 && x1 * x2 <= 0 || x1 == 0 && y1 * y2 <= 0 || x2 == 0 && y1 * y2 <= 0) {
                crossZero = true;
            }
        }
        
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < n; j++) {
                if(rectangles[i].intersect(rectangles[j])) {
                    intersect[i][j] = true;
                }
            }
        }
        
        boolean[] visited = new boolean[n];
        int cnt = 0;
        
        for(int i = 0; i < n; i++) {
            if(!visited[i]) {
                dfs(rectangles, intersect, visited, i,  n);
                cnt++;
            }    
        }
        
        if(crossZero) cnt--;
        
        System.out.println(cnt);
    }
 
    private static void dfs(Rectangle[] rectangles, boolean[][] intersect, boolean[] visited, int i, int n) {
        visited[i] = true;
        
        for(int j = 0; j < n; j++) {
            if(!visited[j] && intersect[i][j]) {
                dfs(rectangles, intersect, visited, j, n);
            }
        }
    }
 
    private static class Rectangle {
        private int x1;
        private int y1;
        private int x2;
        private int y2;
        
        public Rectangle(int x1, int y1, int x2, int y2) {
            this.x1 = x1;
            this.y1 = y1;
            this.x2 = x2;
            this.y2 = y2;
        }
 
        public int getX1() {
            return x1;
        }
 
        public int getY1() {
            return y1;
        }
 
        public int getX2() {
            return x2;
        }
 
        public int getY2() {
            return y2;
        }
        
        public boolean intersect(Rectangle rectangle) {
            int _x1 = rectangle.getX1();
            int _y1 = rectangle.getY1();
            int _x2 = rectangle.getX2();
            int _y2 = rectangle.getY2();
            
            return !(_x2 < x1 || x2 < _x1 || _y2 < y1 || y2 < _y1 || (x1 < _x1 && x2 > _x2 && y1 < _y1 && y2 > _y2) || (_x1 < x1 && _x2 > x2 && _y1 < y1 && _y2 > y2));
        }
    }
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

여기서 조심해야할 것이 있는데, 직사각형 중 원점(0, 0)을 지나는 게 있는지의 여부이다. 하나라도 원점을 지나는 직사각형이 있을 경우, 거북이가 처음 PU명령어를 사용할 필요가 없어지므로, 이 때의 답은 '직사각형 그룹의 갯수 - 1'이 된다. 

 

그리고 두 직사각형이 교차하는 지의 여부를 구하는 조건이 좀 복잡하다;;

혹시 더 쉬운 방법을 아는 분은 댓글을 남겨주시면 감사하겠습니다.(굽신굽신)

 

 

반응형
반응형

문제링크 : https://www.acmicpc.net/problem/1525

 

1525번: 퍼즐

세 줄에 걸쳐서 표에 채워져 있는 아홉 개의 수가 주어진다. 한 줄에 세 개의 수가 주어지며, 빈 칸은 0으로 나타낸다.

www.acmicpc.net

 

필자는 이 문제를 풀 때 '메모리 제한 32MB'라고 써있는 걸 보고, 메모리를 아끼기 위해 최선을 다하며 풀었다. 근데 지금 생각해보면 자바의 경우 256MB로 그렇게 적은 편이 아닌데 굳이 그렇게까지 했어야했나 싶기도 하다^^; 메모리를 아끼기 위해 혼신(?)의 힘을 쏟으며 푼 코드는 아래와 같다.

 

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
126
127
128
129
130
131
132
 
public class Main {
    private static int[] di = {-1100};
    private static int[] dj = {00-11};
    private static final int PUZZLE_SIZE = 3;
    private static final int FLATTED_SIZE = PUZZLE_SIZE * PUZZLE_SIZE;
    private static boolean[][] canSwap = new boolean[FLATTED_SIZE][FLATTED_SIZE];
    
    static {
        for(int i = 0; i < PUZZLE_SIZE; i++) {
            for(int j = 0; j < PUZZLE_SIZE; j++) {
                for(int k = 0; k < 4; k++) {
                    int nextI = i + di[k];
                    int nextJ = j + dj[k];
                    
                    if(nextI >= 0 && nextJ >= 0 && nextI < PUZZLE_SIZE && nextJ < PUZZLE_SIZE) {
                        canSwap[i * PUZZLE_SIZE + j][nextI * PUZZLE_SIZE + nextJ] = true;
                    }
                }
            }
        }
    }
    
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int initPuzzle = 0;
        int initZeroIdx = 0;
        
        for(int i = 0; i < PUZZLE_SIZE; i++) {
            StringTokenizer st = new StringTokenizer(br.readLine());
            
            for(int j = 0; j < PUZZLE_SIZE; j++) {
                int n = Integer.parseInt(st.nextToken());
                initPuzzle = initPuzzle * 10 + n;
                
                if(n == 0) {
                    initZeroIdx = i * PUZZLE_SIZE + j;
                }
            }
        }
        
        int min = bfs(initPuzzle, initZeroIdx);
        
        System.out.println(min);
    }
 
    private static int bfs(int initPuzzle, int initZeroIdx) {
        Queue<Status> queue = new LinkedList<Status>();
        Set<Integer> visited = new HashSet<Integer>();
        
        queue.offer(new Status(initPuzzle, 0, initZeroIdx));
        visited.add(initPuzzle);
        
        while(!queue.isEmpty()) {
            Status poll = queue.poll();
            int puzzle = poll.getPuzzle();
            int times = poll.getTimes();
            int zeroIdx = poll.getZeroIdx();
            
            if(puzzle == 123456780) {
                return times;
            }
 
            for(int i = 0; i < FLATTED_SIZE; i++) {
                if(canSwap[zeroIdx][i]) {
                    int next = swapNo(puzzle, zeroIdx, i);
                    
                    if(!visited.contains(next)) {
                        queue.offer(new Status(next, times + 1, i));
                        visited.add(next);
                    }
                }
            }
        }
        
        return -1;
    }
    
    private static int swapNo(int puzzle, int zeroIdx, int nextIdx) {
        int x = extractNo(puzzle, nextIdx);
        
        puzzle -= x * power(10, FLATTED_SIZE - 1 - nextIdx);
        puzzle += x * power(10, FLATTED_SIZE - 1 - zeroIdx);
        
        return puzzle;
    }
 
    private static int extractNo(int puzzle, int idx) {
        return (puzzle / power(10, FLATTED_SIZE - 1 - idx)) % 10;    
    }
    
    private static int power(int a, int n) {
        int ret = 1;
        
        for(int i = 0; i < n; i++) {
            ret *= a;
        }
        
        return ret;
    }
    
    private static class Status {
        private int puzzle;
        private int times;
        private int zeroIdx;
        
        public Status(int puzzle, int times, int zeroIdx) {
            this.puzzle = puzzle;
            this.times = times;
            this.zeroIdx = zeroIdx;
        }
 
        public int getPuzzle() {
            return puzzle;
        }
 
        public int getTimes() {
            return times;
        }
 
        public int getZeroIdx() {
            return zeroIdx;
        }
    }
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

전형적인 BFS문제이다. 메모리를 절약하기 위해 퍼즐의 상태를 2차원배열이 아닌, 정수로 변환해서 저장하는 것을 볼 수 있다. 또한 일반적으로 BFS를 풀 때는 방문여부(visited)를 boolean배열로 저장하지만, 이 경우에 boolean배열을 이용하려면 최소 876543211 크기의 배열을 선언해야하는데 대략 800MB정도 된다. 반면 Set으로 각각의 정수 값을 넣을 경우, 퍼즐에 배치될 수 있는 수의 모든 경우의 수가 9! = 362,880‬이기 때문에 훨씬 메모리를 절약할 수 있다. 그 밖에도 빈칸의 위치를 바꿀 때, char 배열로 잠깐 바꾼다음 swap하고 다시 정수로 바꾸면 편할텐데 메모리를 아끼기위해 계산을 통해 뽑아내는 눈물나는(?) 노력을 볼 수 있다ㅋㅋㅋ

 

반응형
반응형

문제링크 : https://www.acmicpc.net/problem/1107

 

1107번: 리모컨

첫째 줄에 수빈이가 이동하려고 하는 채널 N (0 ≤ N ≤ 500,000)이 주어진다.  둘째 줄에는 고장난 버튼의 개수 M (0 ≤ M ≤ 10)이 주어진다. 고장난 버튼이 있는 경우에는 셋째 줄에는 고장난 버튼이 주어지며, 같은 버튼이 여러 번 주어지는 경우는 없다.

www.acmicpc.net

낮은 정답률(현재 21%)에 비해 비교적 쉬운 문제다. 물론 필자도 처음 이 문제를 풀 때 엄청 헤맸다...;;; '아놔 그냥 리모컨 고쳐 쓰지 왜 망가진 걸 쓰고 난리야'라고 한탄하면서 풀었던 기억이 난다ㅋㅋㅋ 풀이에 대한 설명을 하자면

 

1. 망가지지 않은 버튼으로 누를 수 있는 채널 중 N과 가장 가까운, N보다 큰 값 upperNo를 구한다. 

   : 버튼을 누른 횟수 = upperNo의 길이 + (upperNo - N)

2. 망가지지 않은 버튼으로 누를 수 있는 채널 중 N과 가장 가까운, N보다 작은 값 lowerNo를 구한다.

   : 버튼을 누른 횟수 = lowerNo의 길이 + (N - lowerNo)

3. +, - 버튼으로만 이동

   : 버튼을 누른 횟수 = N - 100 의 절대값

 

이 3개의 값 중 가장 작은 값을 구하면 된다. 다들 여기까진 쉽게 생각을 할 것 같다. 문제는 1, 2번을 구하는 방법인데, 처음에는 어떻게든 규칙성을 찾으려고 발악을 했으나... 분기가 너무 많았다. 근데 생각을 해보자. 그냥 1씩 더하거나 빼면서 upperNo, lowerNo를 구할 때의 시간복잡도는 얼마일까? O(N)이다. 그냥 N... 아놔... 코드는 아래와같다.

 

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
 
public class Main {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        int m = Integer.parseInt(br.readLine());
        
        if(m > 0) {
            StringTokenizer st = new StringTokenizer(br.readLine());
            boolean[] broken = new boolean[10];
            
            for(int i = 0; i < m; i++) { 
                broken[Integer.parseInt(st.nextToken())] = true;
            }
            
            List<Integer> candidates = new ArrayList<Integer>();
            candidates.add(Math.abs(n - 100));
            
            int upperNo = getUpperNo(n, broken);
            int lowerNo = getLowerNo(n, broken);
            
            if(upperNo != -1) {
                candidates.add(String.valueOf(upperNo).length() + upperNo - n);
            }
            
            if(lowerNo != -1) {
                candidates.add(String.valueOf(lowerNo).length() + n - lowerNo);
            }
            
            Collections.sort(candidates);
            
            System.out.println(candidates.get(0));
        } else {
            System.out.println(Math.min(Math.abs(n - 100), String.valueOf(n).length()));
        }    
    }
    
    private static int getUpperNo(int n, boolean[] broken) {
        boolean allBrokenExceptZero = true;
        
        for(int i = 1; i < 10; i++) {
            if(!broken[i]) {
                allBrokenExceptZero = false;
                break;
            }
        }
        
        if(allBrokenExceptZero) {
            return -1;
        }
        
        while(n < 1000_000) {
            if(isPossible(n, broken)) {
                return n;
            }
            
            n++;
        }
        
        return -1;
    }
    
    private static int getLowerNo(int n, boolean[] broken) {
        boolean allBroken = true;
        
        for(int i = 0; i < 10; i++) {
            if(!broken[i]) {
                allBroken = false;
                break;
            }
        }
        
        if(allBroken) {
            return -1;
        }
        
        while(n >= 0) {
            
            if(isPossible(n, broken)) {
                return n;
            }
            
            n--;
        }
        
        return -1;
    }
    
    private static boolean isPossible(int n, boolean[] broken) {
        if(n == 0) {
            return !broken[0];
        }
        
        while(n > 0) {
            int tmp = n % 10;
            n /= 10;
            
            if(broken[tmp]) {
                return false;
            }
        }
        
        return true;
    }
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

몇 가지를 더 설명하자면, upperNo와 lowerNo가 절대 나올 수 없는 경우가 있다. 이 경우에는 아예 비교 대상에서 제외를 시켜야하는데, upperNo의 경우 1~9까지 모두 망가졌을 경우, lowerNo의 경우 모든 숫자 버튼이 망가졌을 경우에 나올 수 없다. 그 밖에도 N이 5인데 0~4까지 다 망가졌을 경우도 있을 수 있고 upperNo가 1,000,000보다 커질 경우에는 비교의 의미가 없다(N의 최대값이 500,000인데 +버튼만 이용해도 499,900번 누르면 갈 수 있기 때문)

 

 

반응형
반응형

문제링크 : https://www.acmicpc.net/problem/2580

 

2580번: 스도쿠

스도쿠는 18세기 스위스 수학자가 만든 '라틴 사각형'이랑 퍼즐에서 유래한 것으로 현재 많은 인기를 누리고 있다. 이 게임은 아래 그림과 같이 가로, 세로 각각 9개씩 총 81개의 작은 칸으로 이루어진 정사각형 판 위에서 이뤄지는데, 게임 시작 전 몇 몇 칸에는 1부터 9까지의 숫자 중 하나가 쓰여 있다. 나머지 빈 칸을 채우는 방식은 다음과 같다. 각각의 가로줄과 세로줄에는 1부터 9까지의 숫자가 한 번씩만 나타나야 한다. 굵은 선으로 구분되어 있는 3

www.acmicpc.net

단순하게만 생각한다면, '빈 칸이 포함되는 가로줄, 세로줄, 9개의 네모 칸 안의 수를 다 비교해서, 빈칸에 넣을 수 있는 수를 넣으면 되는 거 아닌가?'라고 생각할 수 있다. 이것도 틀린 말은 아니나 소싯적(?) 스도쿠를 조금이라도 해본 사람은 이게 그렇게 간단한 문제는 아니라는 걸 알 것이다. 다 비교해봐도 빈 칸 안에 넣을 수 있는 수가 1개가 넘는 경우가 많기 때문이다. 심지어 이 문제에는 '판을 채우는 방법이 여럿인 경우는 그 중 하나만을 출력한다.'라는 조건이 있다. 그 말은 81개의 모든 칸이 0으로 주어진다고 해도 답이 나와야한다는 얘기다. 뭔가 완전 탐색의 냄새(?)가 나지 않는가?ㅋㅋ 풀이에 대한 설명을 시작하겠다. 일단 이 풀이는 DFS 백트래킹이며, 자세한 건 코드를 보고 설명하는 편이 나을 듯하다.

 

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
 
public class Main {
    private static boolean finished = false;
    
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int[][] puzzle = new int[9][9];
        List<Point> zeroList = new ArrayList<Point>();
        
        for(int i = 0; i < 9; i++) {
            StringTokenizer st = new StringTokenizer(br.readLine());
            
            for(int j = 0; j < 9; j++) {
                puzzle[i][j] = Integer.parseInt(st.nextToken());
                
                if(puzzle[i][j] == 0) {
                    zeroList.add(new Point(i, j));
                }
            }
        }
        
        if(zeroList.size() > 0) {
            dfs(zeroList.get(0), puzzle, zeroList, 0);
        } else {
            printPuzzle(puzzle);
        }    
    }
 
    private static void dfs(Point point, int[][] puzzle, List<Point> zeroList, int depth) {
        if(finished) {
            return;
        }
        
        boolean[] checked = getCandidates(puzzle, point);
        
        for(int k = 1; k <= 9; k++) {
            if(!checked[k]) {
                int i = point.getI();
                int j = point.getJ();
                
                puzzle[i][j] = k;
                
                if(depth == zeroList.size() - 1) {
                    printPuzzle(puzzle);
                    finished = true;
                    return;
                }
                
                dfs(zeroList.get(depth + 1), puzzle, zeroList, depth + 1);            
                puzzle[i][j] = 0;
            }
        }
    }
 
    private static void printPuzzle(int[][] puzzle) {
        StringBuffer sb = new StringBuffer();
        
        for(int i = 0; i < 9; i++) {
            for(int j = 0; j < 9; j++) {
                sb.append(puzzle[i][j] + " ");
            }
            
            sb.append("\n");
        }
        
        System.out.println(sb);
    }
    
    private static boolean[] getCandidates(int[][] puzzle, Point point) {
        int i = point.getI();
        int j = point.getJ();
        boolean[] checked = new boolean[10];
        
        for(int k = 0; k < 9; k++) {
            checked[puzzle[i][k]] = true;
        }
        
        for(int k = 0; k < 9; k++) {
            checked[puzzle[k][j]] = true;
        }
        
        int sI = i / 3 * 3;
        int sJ = j / 3 * 3;
        
        for(int k = sI; k < sI + 3; k++) {
            for(int h = sJ; h < sJ + 3; h++) {
                checked[puzzle[k][h]] = true;
            }
        }
        
        return checked;
    }
    
    private static class Point {
        private int i;
        private int j;
        
        public Point(int i, int j) {
            this.i = i;
            this.j = j;
        }
 
        public int getI() {
            return i;
        }
 
        public int getJ() {
            return j;
        }    
    }
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

 

1. 빈 칸의 위치를 모두 List에 저장한다.

2. 첫번째 빈 칸에 들어갈 수 있는 모든 수를 구한 후, 하나씩 넣은 후, DFS로 다음 빈 칸으로 이동한다.

3. 다음 빈 칸에 대해서도 동일하게(재귀함수) 들어갈 수 있는 모든 수를 구한 후, 하나씩 넣고 다음 칸으로 이동한다.

4. 만약 List에 저장되있는 모든 빈 칸에 대해 숫자가 채워졌다면 함수 실행을 멈추고 값을 출력한다.

5. 만약 현재 넣어본 수가 스도쿠의 조건을 만족할 수 없는 수라면, DFS를 도는 어느 순간, 해당 빈 칸에 들어갈 수 있는 수가 0개로 나올 것이고 해당 조건은 모든 빈 칸을 채울 수 없을 것이다. 해당 depth를 충족시킬 수 없을 것이다. 

6. 아까 빈 칸에 들어갈 수 있는 여러가지 수 중 하나를 일단 넣어봤다. 다른 경우의 수도 알아보려면 아까 수를 넣기 이전 상태로 초기화가 되어야한다. 칸을 다시 빈 칸(0)으로 초기화해준다.(백트래킹)

 

근데 상위권 풀이에 비해 실행시간이 다소 길다...-_- 상위권 풀이를 살펴보니, 굳이 빈칸에 넣을 수 있는 수를 매번 구할 필요가 없다라는 걸 깨달았다. 코드는 아래와 같다.

 

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
 
public class Main {
    private static boolean finished = false;
    private static boolean[][] checkI = new boolean[9][10];
    private static boolean[][] checkJ = new boolean[9][10];
    private static boolean[][][] checkBox = new boolean[3][3][10];
    
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int[][] puzzle = new int[9][9];
        List<Point> zeroList = new ArrayList<Point>();
        
        for(int i = 0; i < 9; i++) {
            StringTokenizer st = new StringTokenizer(br.readLine());
            
            for(int j = 0; j < 9; j++) {
                puzzle[i][j] = Integer.parseInt(st.nextToken());
                
                if(puzzle[i][j] == 0) {
                    zeroList.add(new Point(i, j));
                } else {
                    checkI[i][puzzle[i][j]] = true;
                    checkJ[j][puzzle[i][j]] = true;
                    checkBox[i / 3][j / 3][puzzle[i][j]] = true;
                }
            }
        }
        
        if(zeroList.size() > 0) {
            dfs(zeroList.get(0), puzzle, zeroList, 0);
        } else {
            printPuzzle(puzzle);
        }    
    }
 
    private static void dfs(Point point, int[][] puzzle, List<Point> zeroList, int depth) {
        if(finished) {
            return;
        }
        
        int i = point.getI();
        int j = point.getJ();
        
        for(int k = 1; k <= 9; k++) {
            if(!checkI[i][k] && !checkJ[j][k] && !checkBox[i / 3][j / 3][k]) {
                
                puzzle[i][j] = k;
                checkI[i][k] = true;
                checkJ[j][k] = true;
                checkBox[i / 3][j / 3][k] = true;
                
                if(depth == zeroList.size() - 1) {
                    printPuzzle(puzzle);
                    finished = true;
                    return;
                }
                
                dfs(zeroList.get(depth + 1), puzzle, zeroList, depth + 1);            
                puzzle[i][j] = 0;
                checkI[i][k] = false;
                checkJ[j][k] = false;
                checkBox[i / 3][j / 3][k] = false;
            }
        }
    }
 
    private static void printPuzzle(int[][] puzzle) {
        StringBuffer sb = new StringBuffer();
        
        for(int i = 0; i < 9; i++) {
            for(int j = 0; j < 9; j++) {
                sb.append(puzzle[i][j] + " ");
            }
            
            sb.append("\n");
        }
        
        System.out.println(sb);
    }
 
    private static class Point {
        private int i;
        private int j;
        
        public Point(int i, int j) {
            this.i = i;
            this.j = j;
        }
 
        public int getI() {
            return i;
        }
 
        public int getJ() {
            return j;
        }    
    }
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

 

반응형
반응형

문제링크 : https://www.acmicpc.net/problem/2186

 

2186번: 문자판

첫째 줄에 N(1 ≤ N ≤ 100), M(1 ≤ M ≤ 100), K(1 ≤ K ≤ 5)가 주어진다. 다음 N개의 줄에는 M개의 알파벳 대문자가 주어지는데, 이는 N×M 크기의 문자판을 나타낸다. 다음 줄에는 1자 이상 80자 이하의 영단어가 주어진다. 모든 문자들은 알파벳 대문자이며, 공백 없이 주어진다.

www.acmicpc.net

DFS로 풀면 되는 문제다. 단순 DFS로 풀었을 때의 시간복잡도는... 아... 어떻게 계산해야할까-_- (필자가 나중에 시간이 되면 계산에 도전해보도록 하겠다;;;) 하여간 어마어마(?)할 것이다. 한 번의 탐색에서 같은 칸을 방문할 수 없다고 한다고 해도 시간복잡도가 어마어마할텐데(이 경우에는 백트래킹으로 풀 것이다), 심지어 같은 칸을 여러 번 방문할 수 있다고 한다. 단순 DFS로 풀면 안 된다; 뭔가 대책이 필요하다. 바로 메모이제이션이다. 코드는 아래와 같다.

 

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
 
public class Main {
    private static int[] di = {-1100};
    private static int[] dj = {00-11};
    private static int n;
    private static int m;
    private static int k;
    private static int trgtLen;
    private static int[][][] dp;
    
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        n = Integer.parseInt(st.nextToken());
        m = Integer.parseInt(st.nextToken());
        k = Integer.parseInt(st.nextToken());
        
        char[][] board = new char[n][m];
        
        for(int i = 0; i < n; i++) {
            board[i] = br.readLine().toCharArray();
        }
        
        char[] goal = br.readLine().toCharArray();
        trgtLen = goal.length;
        dp = new int[n][m][trgtLen];
        
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < m; j++) {
                Arrays.fill(dp[i][j], -1);
            }
        }
        
        int cnt = 0;
        
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < m; j++) {                
                if(board[i][j] == goal[0]) {
                    cnt += dfs(board, goal, i, j, 0);
                }
            }
        }
        
        System.out.println(cnt);
    }
 
    private static int dfs(char[][] board, char[] goal, int i, int j, int depth) {
        
        if(dp[i][j][depth] != -1) {
            return dp[i][j][depth];
        }
        
        if(depth == trgtLen - 1) {
            return 1;
        }
        
        int cnt = 0;
        
        for(int a = 1; a <= k; a++) {
            for(int b = 0; b < 4; b++) {
                int nextI = i + di[b] * a;
                int nextJ = j + dj[b] * a;
                
                if(nextI >= 0 && nextJ >= 0 && nextI < n && nextJ < m && board[nextI][nextJ] == goal[depth + 1]) {
                    cnt += dfs(board, goal, nextI, nextJ, depth + 1);
                }
            }
        }
        
        return dp[i][j][depth] = cnt;
    }
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

 

여기서 dp[i][j][x]가 가리키는 값은, 문자판의 (i, j)의 위치를 depth=x 인 경우에 방문했을 때 나올 수 있는 경로의 수이다.

 

위 그림을 통해 좀 더 설명해보겠다. BREAK를 탐색하는 문제라고 가정했을 때 처음 윗쪽 B에서 탐색을 시작한다. 그리고 빨간색 E를 주목하자. E에서는 각각 좌우로 A, K로 가면 답이 나온다. 즉 이 위치에서 정답으로 갈 수 있는 경우의 수는 2개이다. 그리고 이번엔 밑쪽 B에서 탐색을 시작해보자. E에 도착했을 때, 굳이 A, K로 또 탐색을 할 필요가 있을까? 이미 여기에서 정답이 나오는 경우의 수가 2개라는 걸 알지 않는가? 이 정도 설명으로 이해가 됐으리라고 본다. '메모이제이션을 할 때 depth까진 저장할 필요가 없지 않나?'란 생각을 할 수도 있다. 근데 만들어야하는 영단어가 'AABAAA'와 같은, 같은 알파벳이 중복된 것일 수도 있기 때문에 depth에 따른 경우의 수를 저장해야한다.

 

 

반응형
반응형

문제링크 : https://www.acmicpc.net/problem/11053

 

11053번: 가장 긴 증가하는 부분 수열

수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오. 예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {10, 20, 10, 30, 20, 50} 이고, 길이는 4이다.

www.acmicpc.net

총 2가지의 풀이를 소개할 것이다. 1. 내가 이 문제를 푼 방법 2. 상위권 풀이에 있는 방법

 

내 풀이에서 생각해야할 점은 다음과 같다.

1. 수열(seq)의 크기와 똑같은 크기의 배열 max를 선언한다.

2. max[i]가 뜻하는 것은, seq[i]가 선택되었을 때 증가하는 부분 수열 중 가장 긴 길이의 값이다.

 

코드는 아래와 같다.

 

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
 
public class Main {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        int[] seq = new int[n];
        int[] max = new int[n];
        
        StringTokenizer st = new StringTokenizer(br.readLine());
        
        for(int i = 0; i < n; i++) {
            seq[i] = Integer.parseInt(st.nextToken());
        }
        
        max[0= 1;
        
        for(int i = 1; i < n; i++) {
            max[i] = 1;
            
            for(int j = i - 1; j >= 0; j--) {
                
                if(seq[j] < seq[i] && max[j] + 1 >  max[i]) {
                    max[i] = max[j] + 1;
                }
            }
        }
        
        int answer = max[n - 1];
        
        for(int i = n - 2; i >= 0; i--) {
            
            if(max[i] > answer) {
                answer = max[i];
            }
        }
 
        System.out.println(answer);
    }
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

 

두 번재 풀이의 경우, 일단 코드부터 먼저 소개하겠다.

 

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
 
public class Main {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        int[] seq = new int[n];
        int[] partSeq = new int[n];
        StringTokenizer st = new StringTokenizer(br.readLine());
        
        for(int i = 0; i < n; i++) {
            seq[i] = Integer.parseInt(st.nextToken());
            partSeq[i] = -1;
        }
        
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < n; j++) {
                if(partSeq[j] == -1 || partSeq[j] >= seq[i]) {
                    partSeq[j] = seq[i];
                    break;
                }
            }
        }
        
        int answer = 0;
        
        for(int i = 0; i < n; i++) {
            if(partSeq[i] > 0) {
                answer++;
            }
        }
        
        System.out.println(answer);
    }
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

하나의 수열을 예를 들어서 반복문에 대한 디버깅을 해보자.

일단 가장 긴 증가하는 부분수열은 i = 8일 때의 partSeq가 될 것이다. 그 때의 부분수열이 길이 6까지 도달하였으므로 최댓값이 6이 되는 것이다. 가장 멀리까지 간 놈의 길이를 구한다고 생각하면 이해하기 쉽다. 설명하기가 참 어렵다. 아마 필자도 '어떻게 이런 생각을 하지?'란 생각이 들기 때문인 것 같다....;;; 필자가 푼 풀이와 동일한 시간복잡도 O(N^2)을 가지고 있으나 중간에 break로 빠져나오는 부분이 있어서 조금 더 유리한 것 같다.

 

반응형
반응형

문제링크 : https://www.acmicpc.net/problem/1451

 

1451번: 직사각형으로 나누기

첫째 줄에 직사각형의 세로 크기 N과 가로 크기 M이 주어진다. 둘째 줄부터 직사각형에 들어가는 수가 가장 윗 줄부터 한 줄에 하나씩 M개의 수가 주어진다. N과 M은 100보다 작거나 같은 자연수이고, 직사각형엔 적어도 3개의 수가 있다. 또, 직사각형에 들어가는 수는 한 자리의 숫자이다.

www.acmicpc.net

내가 가장 싫어하는 전형적인 그리디 문제이다-_- 아... 이런 문제 진짜 싫다. 하나라도 빠뜨리면 안되는... 실수할 여지도 너무 많고...ㅠㅠ 아무튼 문제에 대한 설명을 해보겠다. 직사각형을 작은 3개의 직사각형으로 나눌 수 있는 경우의 수는 아래 그림과 같이 총 6가지이다.

 

이렇게 총 6가지 경우에 대해 모두 계산을 해서 이 중에 가장 큰 값을 구하면 된다... 코드는 아래와 같다.

 

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
 
public class Main {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        
        int n = Integer.parseInt(st.nextToken());
        int m = Integer.parseInt(st.nextToken());
        int[][] rectangle = new int[n][m];
        
        for(int i = 0; i < n; i++) {
            char[] temp = br.readLine().toCharArray();
            
            for(int j = 0; j < m; j++) {
                rectangle[i][j] = temp[j] - '0';
            }
        }
        
        long max = 0;
        
        for(int i = 1; i < n; i++) {
            long a = getRectangleSum(0, i, 0, m, rectangle);
            
            for(int j = 1; j < m; j++) {
                long b = getRectangleSum(i, n, 0, j, rectangle);
                long c = getRectangleSum(i, n, j, m, rectangle);
                
                long tmp = a * b * c;
                
                if(max < tmp) {
                    max = tmp;
                }
            }
            
            for(int j = i + 1; j < n; j++) {
                long b = getRectangleSum(i, j, 0, m, rectangle);
                long c = getRectangleSum(j, n, 0, m, rectangle);
                
                long tmp = a * b * c;
                
                if(max < tmp) {
                    max = tmp;
                }
            }    
        }
        
        for(int i = n - 1; i > 0; i--) {
            long a = getRectangleSum(i, n, 0, m, rectangle);
            
            for(int j = 1; j < m; j++) {
                long b = getRectangleSum(0, i, 0, j, rectangle);
                long c = getRectangleSum(0, i, j, m, rectangle);
                
                long tmp = a * b * c;
                
                if(max < tmp) {
                    max = tmp;
                }
            }
        }
        
        for(int i = 1; i < m; i++) {
            long a = getRectangleSum(0, n, 0, i, rectangle);
            
            for(int j = 1; j < n; j++) {
                long b = getRectangleSum(0, j, i, m, rectangle);
                long c = getRectangleSum(j, n, i, m, rectangle);
                
                long tmp = a * b * c;
                
                if(max < tmp) {
                    max = tmp;
                }
            }
            
            for(int j = i + 1; j < m; j++) {
                long b = getRectangleSum(0, n, i, j, rectangle);
                long c = getRectangleSum(0, n, j, m, rectangle);
                
                long tmp = a * b * c;
                
                if(max < tmp) {
                    max = tmp;
                }
            }    
        }
        
        for(int i = m - 1; i > 0; i--) {
            long a = getRectangleSum(0, n, i, m, rectangle);
            
            for(int j = 1; j < n; j++) {
                long b = getRectangleSum(0, j, 0, i, rectangle);
                long c = getRectangleSum(j, n, 0, i, rectangle);
                
                long tmp = a * b * c;
                
                if(max < tmp) {
                    max = tmp;
                }
            }
        }
        
        System.out.println(max);
    }
    
    private static long getRectangleSum(int sI, int eI, int sJ, int eJ, int[][] rectangle) {
        long sum = 0;
        
        for(int i = sI; i < eI; i++) {
            for(int j = sJ; j < eJ; j++) {
                sum += rectangle[i][j];
            }
        }
        
        return sum;
    }
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

 

뭔가 메서드로 빼고 싶은 욕구가 용솟음친다... 근데 딱히 뺄 게 없어 보였다. 그나마 메서드로 뺀 코드는 아래와 같다.

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
 
public class Main {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        
        int n = Integer.parseInt(st.nextToken());
        int m = Integer.parseInt(st.nextToken());
        int[][] rectangle = new int[n][m];
        
        for(int i = 0; i < n; i++) {
            char[] temp = br.readLine().toCharArray();
            
            for(int j = 0; j < m; j++) {
                rectangle[i][j] = temp[j] - '0';
            }
        }
        
        long max = 0;
        
        for(int i = 1; i < n; i++) {
            long a = getRectangleSum(0, i, 0, m, rectangle);
            
            max = getMaxVertical(a, rectangle, max, i, n, 0, m);    
            max = getMaxHorizontal(a, rectangle, max, i, n, 0, m);
        }
                
        for(int i = n - 1; i > 0; i--) {
            long a = getRectangleSum(i, n, 0, m, rectangle);
            
            max = getMaxVertical(a, rectangle, max, 0, i, 0, m);        
        }
        
        for(int i = 1; i < m; i++) {
            long a = getRectangleSum(0, n, 0, i, rectangle);
            
            max = getMaxHorizontal(a, rectangle, max, 0, n, i, m);
            max = getMaxVertical(a, rectangle, max, 0, n, i, m);        
        }
        
        for(int i = m - 1; i > 0; i--) {
            long a = getRectangleSum(0, n, i, m, rectangle);
            
            max = getMaxHorizontal(a, rectangle, max, 0, n, 0, i);
        }
        
        System.out.println(max);
    }
 
    private static long getMaxHorizontal(long a, int[][] rectangle, long max, int sI, int eI, int sJ, int eJ) {
        
        for(int j = sI + 1; j < eI; j++) {
            long b = getRectangleSum(sI, j, sJ, eJ, rectangle);
            long c = getRectangleSum(j, eI, sJ, eJ, rectangle);
            
            long tmp = a * b * c;
            
            if(max < tmp) {
                max = tmp;
            }
        }
        
        return max;
    }
 
    private static long getMaxVertical(long a, int[][] rectangle, long max, int sI, int eI, int sJ, int eJ) {
        
        for(int j = sJ + 1; j < eJ; j++) {
            long b = getRectangleSum(sI, eI, sJ, j, rectangle);
            long c = getRectangleSum(sI, eI, j, eJ, rectangle);
            
            long tmp = a * b * c;
            
            if(max < tmp) {
                max = tmp;
            }
        }
        
        return max;
    }
    
    private static long getRectangleSum(int sI, int eI, int sJ, int eJ, int[][] rectangle) {
        long sum = 0;
        
        for(int i = sI; i < eI; i++) {
            for(int j = sJ; j < eJ; j++) {
                sum += rectangle[i][j];
            }
        }
        
        return sum;
    }
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

 

메서드로 빼도 딱히 많은 이점이 있는 것 같지는 않다. 이런 문제는 극혐이나 알고리즘 테스트에 나온다면 풀어야하니 어쩔 수 없이 연습을 해야겠지...ㅠㅠ

 

 

반응형
반응형

문제링크 : https://www.acmicpc.net/problem/7453

 

7453번: 합이 0인 네 정수

문제 정수로 이루어진 크기가 같은 배열 A, B, C, D가 있다. A[a], B[b], C[c], D[d]의 합이 0인 (a, b, c, d) 쌍의 개수를 구하는 프로그램을 작성하시오. 입력 첫째 줄에 배열의 크기 n (1 ≤ n ≤ 4000)이 주어진다. 다음 n개 줄에는 A, B, C, D에 포함되는 정수가 공백으로 구분되어져서 주어진다. 배열에 들어있는 정수의 절댓값은 최대 228이다. 출력 합이 0이 되는 쌍의 개수를 출력한다. 예제 입력 1 복

www.acmicpc.net

이 문제에서 모든 경우의 수를 다 구해본다면, 그 때의 시간복잡도는 O(N^4)이다. N의 최댓값이 4000밖에 되지 않기 때문에 그렇게 푸는 것도 가능할 것 같긴 했으나(해보진 않음;;) 더 효율적인 방법을 알기에 그렇게 하지 않았다.

 

1. A와 B의 합, C와 D의 합에 대한 모든 경우의 수를 각각 subsetAB, subsetCD라는 새로운 배열에 저장한다. 이 때 각각의 subset의 크기는 N * N이 될 것이다.

2. 두 subset을 오름차순으로 정렬한다.

3. 두 subset의 합이 0일 때의 경우의 수를 센다. 이 때 투포인터 알고리즘을 사용한다.

 

투포인터 알고리즘에 대해 자세히 설명하면,

일단 left = 0, right = N * N - 1(subset의 가장 마지막 인덱스)로 초기화한다.

left는 subsetAB의 인덱스를 가리킬 것이고, right는 subsetCD의 인덱스를 가리킬 것이다.

 

현재 각각의 subset은 오름차순으로 정렬되어있다. subsetAB[left] + subsetCD[right]의 값이 0보다 작다면 어떻게 해야할까? left를 증가시켜야한다. 현재의 subsetCD는 가장 큰값이므로 더 증가시킬수가없다. 반대의경우에는 right를 감소시키면된다. 이런식의 탐색을 통해 훨씬 적은 횟수의 비교를 통해 네 배열의 합이 0인 모든경우의수를 구할 수있다. 투포인터를 사용했을 시 시간복잡도는 O(N^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
 
public class Main {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        
        int[] a = new int[n];
        int[] b = new int[n];
        int[] c = new int[n];
        int[] d = new int[n];
        
        for(int i = 0; i < n; i++) {
            StringTokenizer st = new StringTokenizer(br.readLine());
            a[i] = Integer.parseInt(st.nextToken());
            b[i] = Integer.parseInt(st.nextToken());
            c[i] = Integer.parseInt(st.nextToken());
            d[i] = Integer.parseInt(st.nextToken());
        }
        
        int[] subsetAB = getSubset(n, a, b);
        int[] subsetCD = getSubset(n, c, d);
        
        Arrays.sort(subsetAB);
        Arrays.sort(subsetCD);
        
        int left = 0;
        int right = n * n - 1;
        long cnt = 0;
        
        while(left < n * n && right >= 0) {
            int leftVal = subsetAB[left];
            int rightVal = subsetCD[right];
            int tmp = leftVal + rightVal;
            
            if(tmp < 0) {
                while(++left < n * n && subsetAB[left] == leftVal) {
                    // do nothing
                }
            } else if(tmp > 0) {
                while(--right >= 0 && subsetCD[right] == rightVal) {
                    // do nothing
                }
            } else {
                long leftCnt = 1;
                long rightCnt = 1;
                
                while(++left < n * n && subsetAB[left] == leftVal) {
                    leftCnt++;
                }
                
                while(--right >= 0 && subsetCD[right] == rightVal) {
                    rightCnt++;
                }
                
                cnt += leftCnt * rightCnt;
            }
        }
        
        System.out.println(cnt);
    }
 
    private static int[] getSubset(int n, int[] a, int[] b) {
        int[] subset = new int[n * n];
        
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < n; j++) {
                subset[i * n + j] = a[i] + b[j];
            }
        }
        
        return subset;
    }
}
 
cs

 

반응형

+ Recent posts