728x90

N과 M (1)은 순열이었다면 N과 M (2)는 조합이다.

단계별로 풀어보기 백트래킹의 2단계 문제이다.

 

15650번: N과 M (2)

한 줄에 하나씩 문제의 조건을 만족하는 수열을 출력한다. 중복되는 수열을 여러 번 출력하면 안되며, 각 수열은 공백으로 구분해서 출력해야 한다. 수열은 사전 순으로 증가하는 순서로 출력해야 한다.

www.acmicpc.net

 

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int m = in.nextInt();
        boolean[] visited = new boolean[n];
        int[] result = new int[m];
        combination(n, m, 0, visited, result);
    }

    static void combination(int n, int m, int num, boolean[] visited, int[] result) {
        if (num == m) {
            for (int i = 0; i < m; i++) {
                System.out.print(result[i] + " ");
            }
            System.out.println();
        }
        else {
            for (int i = 0; i < n; i++) {
                if(!visited[i]) {
                    if(num != 0) {
                        if (result[num - 1] < i + 1) {
                            visited[i] = true;
                            result[num] = i + 1;
                        }
                        else continue;
                    }
                    else {
                        visited[i] = true;
                        result[num] = i + 1;
                    }
                    combination(n, m, num + 1, visited, result);
                     visited[i] = false;
                }
            }
        }
    }
}

응용할 것도 없이 그냥 조합이기 때문에 쉽게 풀 수 있었다.

728x90

'알고리즘 문제' 카테고리의 다른 글

[백준] 15652번 N과 M (4)  (0) 2020.01.06
[백준] 15651 N과 M (3)  (0) 2020.01.06
[백준] 15649번 N과 M (1)  (0) 2020.01.06
[백준] 14502번 연구소  (0) 2020.01.05
[백준] 12865 평범한 배낭  (0) 2020.01.05
728x90

단계별로 풀어보기 백트래킹의 1단계 문제

 

15649번: N과 M (1)

한 줄에 하나씩 문제의 조건을 만족하는 수열을 출력한다. 중복되는 수열을 여러 번 출력하면 안되며, 각 수열은 공백으로 구분해서 출력해야 한다. 수열은 사전 순으로 증가하는 순서로 출력해야 한다.

www.acmicpc.net

그냥 순열을 구하면 된다.

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int m = in.nextInt();
        boolean[] visited = new boolean[n];
        int[] result = new int[m];
        permutation(n, m, 0, visited, result);
    }

    static void permutation(int n, int m, int num, boolean[] visited, int[] result) {
        if (num == m) {
            for (int i = 0; i < m; i++) {
                System.out.print(result[i] + " ");
            }
            System.out.println();
            return;
        }
        for (int i = 0; i < n; i++) {
            if(!visited[i]) {
                visited[i] = true;
                result[num] = i + 1;
                permutation(n, m, num + 1, visited, result);
                visited[i] = false;
            }
        }
    }
}

순열을 구하는 방법을 모른다면 어려웠을 문제지만 순열을 공부했기 때문에 쉽게 풀 수 있었다.

 

7개월 뒤 8월 16일에 어떠한 것도 보지 않고 다시 풀어보았다. 이번엔 C++로 풀어봤다.

#include <vector>
#include <iostream>
using namespace std;

int n, m;

void permutation(int num, vector<bool> visited, vector<int> result) {
	if (num == m) {
		for (int i = 0; i < result.size(); i++) {
			cout << result[i] << " ";
		}
		cout << '\n';
		return;
	}
	for (int i = 1; i <= n; i++) {
		if (!visited[i]) {
			result[num] = i;
			visited[i] = true;
			permutation(num + 1, visited, result);
			visited[i] = false;
		}
	}
}

int main() {
	cin >> n >> m;
	vector<bool> visited(n + 1, false);
	vector<int> result(m);
	permutation(0, visited, result);
	system("pause");
	return 0;
}

역시 C++이 훨씬 빠르다. 정말 놀라울 정도로 차이가 난다.

728x90

'알고리즘 문제' 카테고리의 다른 글

[백준] 15651 N과 M (3)  (0) 2020.01.06
[백준] 15650번 N과 M (2)  (0) 2020.01.06
[백준] 14502번 연구소  (0) 2020.01.05
[백준] 12865 평범한 배낭  (0) 2020.01.05
[백준] 9251번 LCS (Longest Common Sequence)  (0) 2020.01.04
728x90

삼성 SW 역량 테스트 기출 문제인 14502번

 

14502번: 연구소

인체에 치명적인 바이러스를 연구하던 연구소에서 바이러스가 유출되었다. 다행히 바이러스는 아직 퍼지지 않았고, 바이러스의 확산을 막기 위해서 연구소에 벽을 세우려고 한다. 연구소는 크기가 N×M인 직사각형으로 나타낼 수 있으며, 직사각형은 1×1 크기의 정사각형으로 나누어져 있다. 연구소는 빈 칸, 벽으로 이루어져 있으며, 벽은 칸 하나를 가득 차지한다.  일부 칸은 바이러스가 존재하며, 이 바이러스는 상하좌우로 인접한 빈 칸으로 모두 퍼져나갈 수 있다.

www.acmicpc.net

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int m = in.nextInt();
        int[][] arr = new int[n][m];
        int[][] ori = new int[n][m];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                arr[i][j] = in.nextInt();
                ori[i][j] = arr[i][j];
            }
        }
        int max = 0;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (arr[i][j] == 1 || arr[i][j] == 2) continue;
                for (int k = i; k < n; k++) {
                    for (int l = 0; l < m; l++) {
                        if (k == i && j >= l) continue;
                        if (arr[k][l] == 1 || arr[k][l] == 2) continue;
                        int count = 0;
                        for (int o = k; o < n; o++) {
                            for (int p = 0; p < m; p++) {
                                if (o == k && p <= l) continue;
                                if (arr[o][p] == 1 || arr[o][p] == 2) continue;
                                arr[i][j] = 1;
                                arr[k][l] = 1;
                                arr[o][p] = 1;
                                for (int a = 0; a < n; a++) {
                                    for (int b = 0; b < m; b++) {
                                        if (arr[a][b] == 2) {
                                            if (a == 0 && b == 0) {
                                                if (arr[a + 1][b] == 0) arr[a + 1][b] = 2;
                                                if (arr[a][b + 1] == 0) arr[a][b + 1] = 2;
                                            } else if (a == 0 && b == m - 1) {
                                                if (arr[a + 1][b] == 0) arr[a + 1][b] = 2;
                                                if (arr[a][b - 1] == 0) arr[a][b - 1] = 2;
                                            } else if (a == n - 1 && b == 0) {
                                                if (arr[a - 1][b] == 0) arr[a - 1][b] = 2;
                                                if (arr[a][b + 1] == 0) arr[a][b + 1] = 2;
                                            } else if (a == n - 1 && b == m - 1) {
                                                if (arr[a - 1][b] == 0) arr[a - 1][b] = 2;
                                                if (arr[a][b - 1] == 0) arr[a][b - 1] = 2;
                                            } else if (a == 0) {
                                                if (arr[a + 1][b] == 0) arr[a + 1][b] = 2;
                                                if (arr[a][b + 1] == 0) arr[a][b + 1] = 2;
                                                if (arr[a][b - 1] == 0) arr[a][b - 1] = 2;
                                            } else if (b == 0) {
                                                if (arr[a + 1][b] == 0) arr[a + 1][b] = 2;
                                                if (arr[a - 1][b] == 0) arr[a - 1][b] = 2;
                                                if (arr[a][b + 1] == 0) arr[a][b + 1] = 2;
                                            } else if (a == n - 1) {
                                                if (arr[a][b - 1] == 0) arr[a][b - 1] = 2;
                                                if (arr[a - 1][b] == 0) arr[a - 1][b] = 2;
                                                if (arr[a][b + 1] == 0) arr[a][b + 1] = 2;
                                            } else if (b == m - 1) {
                                                if (arr[a + 1][b] == 0) arr[a + 1][b] = 2;
                                                if (arr[a][b - 1] == 0) arr[a][b - 1] = 2;
                                                if (arr[a - 1][b] == 0) arr[a - 1][b] = 2;
                                            } else {
                                                if (arr[a + 1][b] == 0) arr[a + 1][b] = 2;
                                                if (arr[a - 1][b] == 0) arr[a - 1][b] = 2;
                                                if (arr[a][b + 1] == 0) arr[a][b + 1] = 2;
                                                if (arr[a][b - 1] == 0) arr[a][b - 1] = 2;
                                            }
                                        }
                                    }
                                }
                                for (int a = n - 1; a >= 0; a--) {
                                    for (int b = m - 1; b >= 0; b--) {
                                        if (arr[a][b] == 2) {
                                            if (a == 0 && b == 0) {
                                                if (arr[a + 1][b] == 0) arr[a + 1][b] = 2;
                                                if (arr[a][b + 1] == 0) arr[a][b + 1] = 2;
                                            } else if (a == 0 && b == m - 1) {
                                                if (arr[a + 1][b] == 0) arr[a + 1][b] = 2;
                                                if (arr[a][b - 1] == 0) arr[a][b - 1] = 2;
                                            } else if (a == n - 1 && b == 0) {
                                                if (arr[a - 1][b] == 0) arr[a - 1][b] = 2;
                                                if (arr[a][b + 1] == 0) arr[a][b + 1] = 2;
                                            } else if (a == n - 1 && b == m - 1) {
                                                if (arr[a - 1][b] == 0) arr[a - 1][b] = 2;
                                                if (arr[a][b - 1] == 0) arr[a][b - 1] = 2;
                                            } else if (a == 0) {
                                                if (arr[a + 1][b] == 0) arr[a + 1][b] = 2;
                                                if (arr[a][b + 1] == 0) arr[a][b + 1] = 2;
                                                if (arr[a][b - 1] == 0) arr[a][b - 1] = 2;
                                            } else if (b == 0) {
                                                if (arr[a + 1][b] == 0) arr[a + 1][b] = 2;
                                                if (arr[a - 1][b] == 0) arr[a - 1][b] = 2;
                                                if (arr[a][b + 1] == 0) arr[a][b + 1] = 2;
                                            } else if (a == n - 1) {
                                                if (arr[a][b - 1] == 0) arr[a][b - 1] = 2;
                                                if (arr[a - 1][b] == 0) arr[a - 1][b] = 2;
                                                if (arr[a][b + 1] == 0) arr[a][b + 1] = 2;
                                            } else if (b == m - 1) {
                                                if (arr[a + 1][b] == 0) arr[a + 1][b] = 2;
                                                if (arr[a][b - 1] == 0) arr[a][b - 1] = 2;
                                                if (arr[a - 1][b] == 0) arr[a - 1][b] = 2;
                                            } else {
                                                if (arr[a + 1][b] == 0) arr[a + 1][b] = 2;
                                                if (arr[a - 1][b] == 0) arr[a - 1][b] = 2;
                                                if (arr[a][b + 1] == 0) arr[a][b + 1] = 2;
                                                if (arr[a][b - 1] == 0) arr[a][b - 1] = 2;
                                            }
                                        }
                                    }
                                }
                                count = 0;
                                for (int a = 0; a < n; a++) {
                                    for (int b = 0; b < m; b++) {
                                        if(arr[a][b] == 0) count++;
                                    }
                                }
                                if(count > max) {
                                    max = count;
                                }
                                for (int a = 0; a < n; a++) {
                                    for (int b = 0; b < m; b++) {
                                        arr[a][b] = ori[a][b];
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        System.out.println(max);
    }
}

살다살다 8중 for문을 쓸 줄이야
내가 조합(Combination)을 코드로 구현할 줄 몰라서 무식한 방법으로 했다

예제 입력을 입력으로 넣었을 때는 모두 옳은 답이 나오는데 제출하면 틀리다고 한다.

예제 입력1
예제 입력2
예제 입력3

 

아직도 못 풀었지만 꼭 내 손으로 풀 거다

 

2020.01.14

이후에 순열과 조합 알고리즘을 공부하고 오늘 다시 도전해보았다

def permutation(result, num, n, li):
    if num == 3:
        v = [[False] * m for i in range(n)]
        import collections
        q = collections.deque()
        for i in virus:
            q.append((i[0], i[1]))
        while q:
            cur = q.popleft()
            v[cur[0]][cur[1]] = True
            if cur[0] - 1 >= 0 and li[cur[0] - 1][cur[1]] == 0 and not v[cur[0] - 1][cur[1]]:
                q.append((cur[0] - 1, cur[1]))
            if cur[0] + 1 < n and li[cur[0] + 1][cur[1]] == 0 and not v[cur[0] + 1][cur[1]]:
                q.append((cur[0] + 1, cur[1]))
            if cur[1] - 1 >= 0 and li[cur[0]][cur[1] - 1] == 0 and not v[cur[0]][cur[1] - 1] :
                q.append((cur[0], cur[1] - 1))
            if cur[1] + 1 < m and li[cur[0]][cur[1] + 1] == 0 and not v[cur[0]][cur[1] + 1]:
                q.append((cur[0], cur[1] + 1))
        count = 0
        for i in range(n):
            for j in range(m):
                if li[i][j] == 0 and not v[i][j]:
                    count += 1
        c.append(count)
        return
    for i in range(n):
        for j in range(m):
            if not visited[i][j]:
                if li[i][j] == 0:
                    if num > 0:
                        if result[num - 1][0] < i:
                            result[num] = (i, j)
                            visited[i][j] = True
                            li[i][j] = 1
                            permutation(result, num + 1, n, li)
                            visited[i][j] = False
                            li[i][j] = 0
                        elif result[num - 1][0] == i and result[num - 1][1] < j:
                            result[num] = (i, j)
                            visited[i][j] = True
                            li[i][j] = 1
                            permutation(result, num + 1, n, li)
                            visited[i][j] = False
                            li[i][j] = 0
                        else:
                            continue
                    else:
                        result[num] = (i, j)
                        visited[i][j] = True
                        li[i][j] = 1
                        permutation(result, num + 1, n, li)
                        visited[i][j] = False
                        li[i][j] = 0
from sys import stdin
n, m = list(map(int, stdin.readline().split()))
li = []
virus = []
for i in range(n):
    temp = list(map(int, stdin.readline().split()))
    li.append(temp)
    for j in range(m):
        if temp[j] == 2:
            virus.append((i, j))
visited = [[False] * m for i in range(n)]
r = [(0, 0)] * 3
c = []
permutation(r, 0, n, li)
print(max(c))

시간초과가 뜬다... 조합이 재귀함수라서 그런걸까

 

6시간 뒤

성공! 위와 코드는 똑같은데 큐에 들어가 있는 것을 중복으로 집어넣는 것을 방지해주었더니 바로 해결됐다.

오늘 또 교훈을 얻는다. 큐에 넣을 때 visited를 True로 바꾸자

def permutation(result, num, n, li):
    if num == 3:
        v = [[False] * m for i in range(n)]
        import collections
        q = collections.deque()
        for i in virus:
            q.append((i[0], i[1]))
        while q:
            cur = q.popleft()
            if not v[cur[0]][cur[1]] and li[cur[0]][cur[1]] == 0:
                v[cur[0]][cur[1]] = True
            if cur[0] - 1 >= 0 and li[cur[0] - 1][cur[1]] == 0 and not v[cur[0] - 1][cur[1]]:
                q.append((cur[0] - 1, cur[1]))
                v[cur[0] - 1][cur[1]] = True
            if cur[0] + 1 < n and li[cur[0] + 1][cur[1]] == 0 and not v[cur[0] + 1][cur[1]]:
                q.append((cur[0] + 1, cur[1]))
                v[cur[0] + 1][cur[1]] = True
            if cur[1] - 1 >= 0 and li[cur[0]][cur[1] - 1] == 0 and not v[cur[0]][cur[1] - 1] :
                q.append((cur[0], cur[1] - 1))
                v[cur[0]][cur[1] - 1] = True
            if cur[1] + 1 < m and li[cur[0]][cur[1] + 1] == 0 and not v[cur[0]][cur[1] + 1]:
                q.append((cur[0], cur[1] + 1))
                v[cur[0]][cur[1] + 1] = True
        count = 0
        for i in range(n):
            for j in range(m):
                if li[i][j] == 0 and not v[i][j]:
                    count += 1
        c.append(count)
        return
    for i in range(n):
        for j in range(m):
            if not visited[i][j]:
                if li[i][j] == 0:
                    if num > 0:
                        if result[num - 1][0] < i:
                            result[num] = (i, j)
                            visited[i][j] = True
                            li[i][j] = 1
                            permutation(result, num + 1, n, li)
                            visited[i][j] = False
                            li[i][j] = 0
                        elif result[num - 1][0] == i and result[num - 1][1] < j:
                            result[num] = (i, j)
                            visited[i][j] = True
                            li[i][j] = 1
                            permutation(result, num + 1, n, li)
                            visited[i][j] = False
                            li[i][j] = 0
                        else:
                            continue
                    else:
                        result[num] = (i, j)
                        visited[i][j] = True
                        li[i][j] = 1
                        permutation(result, num + 1, n, li)
                        visited[i][j] = False
                        li[i][j] = 0
from sys import stdin
n, m = list(map(int, stdin.readline().split()))
li = []
virus = []
for i in range(n):
    temp = list(map(int, stdin.readline().split()))
    li.append(temp)
    for j in range(m):
        if temp[j] == 2:
            virus.append((i, j))
visited = [[False] * m for i in range(n)]
r = [(0, 0)] * 3
c = []
permutation(r, 0, n, li)
print(max(c))
728x90

'알고리즘 문제' 카테고리의 다른 글

[백준] 15650번 N과 M (2)  (0) 2020.01.06
[백준] 15649번 N과 M (1)  (0) 2020.01.06
[백준] 12865 평범한 배낭  (0) 2020.01.05
[백준] 9251번 LCS (Longest Common Sequence)  (0) 2020.01.04
[백준] 1904번 01타일  (0) 2020.01.04
728x90

단계별로 풀어보기 동적계획법1의 마지막 단계 (14단계) 12865문제

 

12865번: 평범한 배낭

첫 줄에 물품의 수 N(1 ≤ N ≤ 100)과 준서가 버틸 수 있는 무게 K(1 ≤ K ≤ 100,000)가 주어진다. 두 번째 줄부터 N개의 줄에 거쳐 각 물건의 무게 W(1 ≤ W ≤ 100,000)와 해당 물건의 가치 V(0 ≤ V ≤ 1,000)가 주어진다. 입력으로 주어지는 모든 수는 정수이다.

www.acmicpc.net

그 유명한 0/1 Knapsack 문제이다.

이번학기 알고리즘 수업 시간에 아주 많이 다룬 문제라서 쉽게 풀 수 있었다.

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int maxWeight = in.nextInt();
        int[] weight = new int[n];
        int[] value = new int[n];
        for (int i = 0; i < 2 * n; i++) {
            if(i % 2 == 0) weight[i / 2] = in.nextInt();
            else value[i / 2] = in.nextInt();
        }
        int[][] arr = new int[n + 1][maxWeight + 1];
        for (int i = 0; i <= n; i++) {
            for (int j = 0; j <= maxWeight; j++) {
                if (i == 0 || j == 0) {
                    arr[i][j] = 0;
                } else if (weight[i - 1] <= j) {
                    arr[i][j] = Integer.max(arr[i - 1][j], value[i - 1] + arr[i - 1][j - weight[i - 1]]);
                }
                else {
                    arr[i][j] = arr[i - 1][j];
                }
            }
        }
        System.out.println(arr[n][maxWeight]);
    }
}

 

728x90

'알고리즘 문제' 카테고리의 다른 글

[백준] 15649번 N과 M (1)  (0) 2020.01.06
[백준] 14502번 연구소  (0) 2020.01.05
[백준] 9251번 LCS (Longest Common Sequence)  (0) 2020.01.04
[백준] 1904번 01타일  (0) 2020.01.04
[백준] 1003번 피보나치 함수  (0) 2020.01.04
728x90

단계별로 풀어보기 동적계획법1의 14단계 문제 LCS

이번 학기 파이썬 수업에서 배웠던 거라 쉽게 풀 수 있었다.

 

9251번: LCS

LCS(Longest Common Subsequence, 최장 공통 부분 수열)문제는 두 수열이 주어졌을 때, 모두의 부분 수열이 되는 수열 중 가장 긴 것을 찾는 문제이다. 예를 들어, ACAYKP와 CAPCAK의 LCS는 ACAK가 된다.

www.acmicpc.net

 

public class Baek9251 {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String n = in.next();
        String m = in.next();
        int[][] arr = new int[n.length() + 1][m.length() + 1];
        for (int i = 0; i < n.length(); i++) {
            for (int j = 0; j < m.length(); j++) {
                if (i == 0 || j == 0) {
                    arr[i][j] = 0;
                }
                if (n.charAt(i) == m.charAt(j)) {
                    arr[i + 1][j + 1] = arr[i][j] + 1;
                }
                else {
                    arr[i + 1][j + 1] = Integer.max(arr[i][j + 1], arr[i + 1][j]);
                }
            }
        }
        System.out.println(arr[n.length()][m.length()]);
    }
}

 

728x90

'알고리즘 문제' 카테고리의 다른 글

[백준] 14502번 연구소  (0) 2020.01.05
[백준] 12865 평범한 배낭  (0) 2020.01.05
[백준] 1904번 01타일  (0) 2020.01.04
[백준] 1003번 피보나치 함수  (0) 2020.01.04
[백준] 1436번 영화감독 숌  (0) 2020.01.04
728x90
 

1904번: 01타일

지원이에게 2진 수열을 가르쳐 주기 위해, 지원이 아버지는 그에게 타일들을 선물해주셨다. 그리고 이 각각의 타일들은 0 또는 1이 쓰여 있는 낱장의 타일들이다. 어느 날 짓궂은 동주가 지원이의 공부를 방해하기 위해 0이 쓰여진 낱장의 타일들을 붙여서 한 쌍으로 이루어진 00 타일들을 만들었다. 결국 현재 1 하나만으로 이루어진 타일 또는 0타일을 두 개 붙인 한 쌍의 00타일들만이 남게 되었다. 그러므로 지원이는 타일로 더 이상 크기가 N인 모든 2진 수

www.acmicpc.net

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int[] arr = new int[1000001];
        arr[1] = 1;
        arr[2] = 2;
        for (int i = 3; i < 1000001; i++) {
            arr[i] = arr[i - 2] + arr[i - 1];
        }
        System.out.print(arr[n] % 15746);
    }
}

이렇게 했는데 자꾸 틀렸다는거다

아무리 봐도 맞는데 뭐가 틀리다는건지 몰라서 너무 답답했지만 그래도 스스로 풀어내겠다는 오기로 풀었다

그런데도 계속 틀리다는거다

그래서 결국 구글링을 해봤더니 다들 저장할 때부터 15746으로 나눈 나머지를 저장하더라

설마 하고 똑같은 코드에 % 15746 이것만 붙여서 했더니 맞았다고 떴다.

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int[] arr = new int[1000001];
        arr[1] = 1;
        arr[2] = 2;
        for (int i = 3; i < 1000001; i++) {
            arr[i] = arr[i - 2] % 15746 + arr[i - 1] % 15746;
        }
        System.out.print(arr[n] % 15746);
    }
}

너무 허무했다.

길이가 N인 2진 수열의 개수를 15746으로 나눈 나머지를 출력하라고 해서 출력할 때만 15746으로 나눈 나머지를 출력했는데 왜 저장할 때도 15746으로 나눈 나머지를 저장해야 하는지 모르겠었다.

그런데 생각해보니 피보나치 수열은 기하급수적으로 증가하기 때문에 오버플로우가 난다.

int로 하면 47번째부터, long으로 해도 93번째부터 오버플로우가 난다.

따라서 애초에 저장할 때 나머지를 저장해주어 오버플로우를 방지한 것이다.

몇 분만에 푼 문제를 괜히 몇 시간 시간낭비했다는 생각이 들었었지만 덕분에 깨달은 게 있으니 다행인 것 같다. 다음부턴 이런 실수 하지 말아야지.

728x90
728x90

https://www.acmicpc.net/problem/1003

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int[] zero = new int[41];
        int[] one = new int[41];
        zero[0] = 1;
        one[0] = 0;
        zero[1] = 0;
        one[1] = 1;
        for(int i = 2; i <= 40; i++) {
            zero[i] = zero[i - 2] + zero[i - 1];
            one[i] = one[i - 2] + one[i - 1];
        }
        for(int i = 0; i < n; i++) {
            int num = in.nextInt();
            System.out.print(zero[num] + " " + one[num]);
            System.out.println();
        }
    }
}

 

제한시간이 0.25초이기 때문에 재귀함수로 직접 호출해서 호출될 때마다 count를 늘리는 방식으로는 할 수 없다.

따라서 동적 계획법을 사용해야하는데 그러기 위해서 규칙성을 찾았다.

fibonacci(0)은 fibonacci(0)을 1번, fibonacci(1)을 0번 호출한다.

fibonacci(1)은 fibonacci(0)을 0번, fibonacci(1)을 1번 호출한다.

그 다음부터는 호출하는 횟수가 피보나치 수열대로 간다.

즉 앞의 두 개의 호출 횟수를 더한 것이 호출 횟수가 된다.

 

728x90
728x90

백준 온라인 저지 단계별로 풀어보기 브루트포스 5단계 문제 1486번

https://www.acmicpc.net/problem/1436

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        ArrayList list = new ArrayList<>();
        for (int i = 0; i < 3000000; i++) {
            if(String.valueOf(i).contains("666"))
                list.add(i);
        }
        System.out.println(list.get(n - 1));
    }
}

처음에는

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        String s = "666";
        HashSet set = new HashSet<>();
        for (int i = 0; i < 10000; i++) {
            if(String.valueOf(i).length() == 1) {
                set.add(Integer.parseInt(s + i));
                set.add(Integer.parseInt(i + s));
            } 
            else if (String.valueOf(i).length() == 2) {
                set.add(Integer.parseInt(s + i));
                set.add(Integer.parseInt(i + s));
                set.add(Integer.parseInt(String.valueOf(i).charAt(0) + s + String.valueOf(i).charAt(1)));
            }
            else if (String.valueOf(i).length() == 3) {
                set.add(Integer.parseInt(s + i));
                set.add(Integer.parseInt(i + s));
                set.add(Integer.parseInt(String.valueOf(i).charAt(0) + s + String.valueOf(i).substring(1, 3)));
                set.add(Integer.parseInt(String.valueOf(i).substring(0, 2) + s + String.valueOf(i).charAt(2)));
            }
            else {
                set.add(Integer.parseInt(s + i));
                set.add(Integer.parseInt(i + s));
                set.add(Integer.parseInt(String.valueOf(i).charAt(0) + s + String.valueOf(i).substring(1, 4)));
                set.add(Integer.parseInt(String.valueOf(i).substring(0, 2) + s + String.valueOf(i).substring(2, 4)));
                set.add(Integer.parseInt(String.valueOf(i).substring(0, 3) + s + String.valueOf(i).charAt(3)));
            }
        }
        ArrayList list = new ArrayList<>(set);
        list.sort((a, b) -> a - b);
        System.out.println(list.get(n - 1));
    }
}

이렇게 했는데 자꾸 틀렸다고 나오는거다.

그래서 포기하고 구글링을 해봤더니 자바의 String 클래스에 contains()라는 메소드가 있었다.

Java10 API String 클래스의 contains 메소드

https://docs.oracle.com/javase/10/docs/api/java/lang/String.html

 

String (Java SE 10 & JDK 10 )

Compares two strings lexicographically. The comparison is based on the Unicode value of each character in the strings. The character sequence represented by this String object is compared lexicographically to the character sequence represented by the argum

docs.oracle.com

이 메소드를 이용해서 0부터 (넉넉하게) 3000000까지 완전히 브루트포스한 방법으로 성공하긴 했는데 아까 그 코드가 왜 틀렸는지가 너무 궁금했다.

그래서 그 리스트를 다 출력해서 복사해서 워드에 붙여넣고 줄번호를 넣어서 비교해봤다.

 

확실히 결과가 다르긴 한데 어디서 부터 왜 잘못된건지 찾아보았다.

비교해보니 121번째 숫자부터 잘못되었다. 보니까 int를 String으로 변환한 후 그것을 concatenation했기 때문에 0이나 00이나 int로는 똑같은 0이기 때문에 00 같은 경우는 빠진 것이었다.

내가 처음에 한 방법은 0부터 큰 숫자를 찾은 것이 아니기 때문에 HashSet을 이용해서 유일하게 만든 후 그것을 ArrayList로 만들고 따로 정렬을 했지만 정답을 낸 이 방법은 정렬을 할 필요도 없었다.

물론 복잡도는 더 높겠지만 이 유형 자체가 브루트포스이기 때문에 무식하게 풀어도 시간초과가 나지 않았다.

728x90
728x90

단계별 풀기의 브루트포스 4번째 단계 문제 1018번 체스판 다시 칠하기

백준 온라인 저지 단계별 풀기 브루트포스

 

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int m = in.nextInt();
        char[][] arr = new char[n][m];
        String[] starr = new String[n];
        for (int i = 0; i < n; i++) {
            starr[i] = in.next();
        }
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                arr[i][j] = starr[i].charAt(j);
            }
        }
        int min = 2500;
        //첫번째 칸이 흰색인 경우 case1
        //첫번째 칸이 검은색인 경우 case2
        for (int i = 0; i <= n - 8; i++) {
            for (int j = 0; j <= m - 8; j++) {
                int case1 = 0;
                int case2 = 0;
                for (int k = 0; k < 8; k++) {
                    for (int l = 0; l < 8; l++) {
                        if (arr[i + k][j + l] == 'W') {
                            if (k % 2 == 0 && l % 2 == 0) {
                                case2++;
                            }
                            else if (k % 2 == 0 && l % 2 == 1) {
                                case1++;
                            }
                            else if (k % 2 == 1 && l % 2 == 0) {
                                case1++;
                            }
                            else {
                                case2++;
                            }
                        }
                        else {
                            if (k % 2 == 0 && l % 2 == 0) {
                                case1++;
                            }
                            else if (k % 2 == 0 && l % 2 == 1) {
                                case2++;
                            }
                            else if (k % 2 == 1 && l % 2 == 0) {
                                case2++;
                            }
                            else {
                                case1++;
                            }
                        }
                    }
                }
                if (case1 < min) {
                    min = case1;
                }
                if (case2 < min) {
                    min = case2;
                }
            }
        }
        System.out.println(min);
    }
}
728x90

+ Recent posts