728x90

단계별로 풀어보기 DFS와 BFS의 1단계 문제

 

1260번: DFS와 BFS

첫째 줄에 정점의 개수 N(1 ≤ N ≤ 1,000), 간선의 개수 M(1 ≤ M ≤ 10,000), 탐색을 시작할 정점의 번호 V가 주어진다. 다음 M개의 줄에는 간선이 연결하는 두 정점의 번호가 주어진다. 어떤 두 정점 사이에 여러 개의 간선이 있을 수 있다. 입력으로 주어지는 간선은 양방향이다.

www.acmicpc.net

이번에는 파이썬으로 풀어봤다.

class Graph:
    def __init__(self, n):
        self.data = {}
        for i in range(1, n + 1):
            self.data[i] = set()
    def add_edge(self, n, m):
        self.data[n].add(m)
        self.data[m].add(n)
    def dfs(self, start):
        visited = [False] * (len(self.data) + 1)
        stack = []
        stack.append(start)
        while stack:
            cur = stack.pop()
            if not visited[cur]:
                print(cur, end=" ")
            visited[cur] = True
            temp = []
            for i in self.data[cur]:
                if not visited[i]:
                    temp.append(i)
            temp.sort()
            temp.reverse()
            stack.extend(temp)
    def bfs(self, start):
        import collections
        visited = [False] * (len(self.data) + 1)
        queue = collections.deque()
        queue.append(start)
        while queue:
            cur = queue.popleft()
            if not visited[cur]:
                print(cur, end=' ')
            visited[cur] = True
            temp = []
            for i in self.data[cur]:
                if not visited[i]:
                    temp.append(i)
            temp.sort()
            queue.extend(temp)
from sys import stdin

node_edge_start = list(map(int, stdin.readline().split()))
graph = Graph(node_edge_start[0])
li = []
for i in range(0, node_edge_start[1]):
    rawInput = list(map(int, stdin.readline().split()))
    graph.add_edge(rawInput[0], rawInput[1])
graph.dfs(node_edge_start[2])
print()
graph.bfs(node_edge_start[2])

 

728x90

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

[백준] 2667번 단지번호붙이기  (0) 2020.01.08
[백준] 2606번 바이러스  (0) 2020.01.08
[백준] 1912 연속합 (미해결)  (0) 2020.01.07
[백준] 9963번 N-Queen  (0) 2020.01.06
[백준] 15652번 N과 M (4)  (0) 2020.01.06
728x90
 

1912번: 연속합

첫째 줄에 정수 n(1 ≤ n ≤ 100,000)이 주어지고 둘째 줄에는 n개의 정수로 이루어진 수열이 주어진다. 수는 -1,000보다 크거나 같고, 1,000보다 작거나 같은 정수이다.

www.acmicpc.net

처음에는 쉬운데 정답률이 왜 27%밖에 안 되지? 하고 쉽게 풀었다.

import java.util.ArrayList;
import java.util.Scanner;

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 < n; i++) {
            list.add(in.nextInt());
        }
        int[][] arr = new int[n][n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if(i < j)
                    continue;
                if(i == j)
                    arr[i][j] = list.get(j);
                else {
                    arr[i][j] = arr[i-1][j] + list.get(i);
                }
            }
        }
        int max = arr[0][0];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if(i < j) continue;
                if (arr[i][j] > max) {
                    max = arr[i][j];
                }
            }
        }
        System.out.println(max);
    }
}

이렇게 제출했더니 메모리 초과가 났다.

 

그래서 아 동적계획법은 생각보다 메모리를 아껴쓸 수가 있지? 하고

import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int[] list = new int[n];
        for (int i = 0; i < n; i++) {
            list[i] = in.nextInt();
        }
        int[] arr = new int[n];
        int max = list[0];
        for (int i = 0; i < n; i++) {
            for (int j = i; j < n; j++) {
                if (i == j) arr[j] = list[i];
                else arr[j] = arr[j - 1] + list[j];
                if(arr[j] > max) max = arr[j];
            }
        }
        System.out.println(max);
    }
}

이렇게 했더니 시간초과가 났다.

꼭 내 손으로 풀어낼거다.

728x90

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

[백준] 2606번 바이러스  (0) 2020.01.08
[백준] 1260번 DFS와 BFS  (0) 2020.01.08
[백준] 9963번 N-Queen  (0) 2020.01.06
[백준] 15652번 N과 M (4)  (0) 2020.01.06
[백준] 15651 N과 M (3)  (0) 2020.01.06
728x90

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

그 유명한 N-Queens Problem이다.

 

9663번: N-Queen

N-Queen 문제는 크기가 N × N인 체스판 위에 퀸 N개를 서로 공격할 수 없게 놓는 문제이다. N이 주어졌을 때, 퀸을 놓는 방법의 수를 구하는 프로그램을 작성하시오.

www.acmicpc.net

이번학기 알고리즘 시간에 정말 잘 배운 문제라 쉽게 풀 수 있었다.

import java.util.Scanner;

public class Main {
    static int count = 0;
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int[] col = new int[n];
        queen(col, n, 0);
        System.out.println(count);
    }

    static void queen(int[] col, int n, int num) {
        if (num == n) {
            count++;
            return;
        }
        for (int i = 0; i < n; i++) {
            if (promising(col, num, i)) {
                 col[num] = i;
                 queen(col, n, num + 1);
                 col[num] = 0;
            }
        }
    }
    static boolean promising(int[] col, int r, int c) {
        for (int i = 0; i < r; i++) {
            if(col[i] == c || Math.abs(c - col[i]) == Math.abs(r - i)) {
                return false;
            }
        }
        return true;
    }
}

728x90

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

[백준] 1260번 DFS와 BFS  (0) 2020.01.08
[백준] 1912 연속합 (미해결)  (0) 2020.01.07
[백준] 15652번 N과 M (4)  (0) 2020.01.06
[백준] 15651 N과 M (3)  (0) 2020.01.06
[백준] 15650번 N과 M (2)  (0) 2020.01.06
728x90

N과 M (4)는 중복조합 문제이다.

 

15652번: N과 M (4)

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

www.acmicpc.net

 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main{
    public static void main(String[] args) {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String s = "";
        StringBuilder sb = new StringBuilder();
        try {
            s = br.readLine();
        } catch (IOException e) {}
        StringTokenizer st = new StringTokenizer(s);
        int n = Integer.parseInt(st.nextToken());
        int m = Integer.parseInt(st.nextToken());
        int[] result = new int[m];
        permutationWithRepetition(n, m, 0, result, sb);
        System.out.println(sb);
    }
    static void permutationWithRepetition(int n, int m, int num, int[] result, StringBuilder sb) {
        if (num == m) {
            for (int i = 0; i < m; i++) {
                sb.append(result[i] + " ");
            }
            sb.append("\n");
            return;
        }
        for (int i = 0; i < n; i++) {
            if(num != 0 && result[num - 1] > i + 1)
                continue;
            else {
                result[num] = i + 1;
                permutationWithRepetition(n, m, num + 1, result, sb);
            }
        }
    }
}

N과 M (3)과 똑같은 코드에

if(num != 0 && result[num - 1] > i + 1)
    continue;

이 조건만 추가해줬다.

728x90

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

[백준] 1912 연속합 (미해결)  (0) 2020.01.07
[백준] 9963번 N-Queen  (0) 2020.01.06
[백준] 15651 N과 M (3)  (0) 2020.01.06
[백준] 15650번 N과 M (2)  (0) 2020.01.06
[백준] 15649번 N과 M (1)  (0) 2020.01.06
728x90

이 문제는 중복순열 문제이다.

 

15651번: N과 M (3)

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

www.acmicpc.net

N과 M (1), N과 M (2)를 쉽게 풀었기 때문에 N과 M (3)을 보자마자 이건 더 쉬운데? 했다.

중복순열이기 때문에 boolean 타입의 visited[n] 배열을 따로 유지할 필요가 없어서 코드도 더 짧고 더 쉬웠다.

15649번 코드에서 visited 관련된 코드만 삭제한 코드인

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[] result = new int[m];
        permutationWithRepetition(n, m, 0, result);
    }

    static void permutationWithRepetition(int n, int m, int num, 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++) {
            result[num] = i + 1;
            permutationWithRepetition(n, m, num + 1, result);
        }
    }
}

이렇게 제출했다.

그랬더니

시간초과가 났다.

 

그래서 이렇게 해봤는데

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[] result = new int[m];
        for(int i = 0; i < Math.pow(n, m); i++) {
            for (int j = 0; j < m; j++) {
                System.out.print((int)(i / Math.pow(n, m - j - 1)) % n + 1 + " ");
            }
            System.out.println();
        }
    }
}

이래도 시간초과가 났다.

그래서 동적계획법으로 해야하나 하고 정말 두 시간 동안 별 짓을 다 해봤다.

그런데도 계속 시간 초과가 나는거다.

내가 정답률 70% 짜리 문제에 이렇게 시간을 투자하고 있다는게 너무 어이없어서 결국 구글링을 해봤다.

그랬더니 시간 초과의 원인은 바로 입출력에 있었다.

내가 처음 짠 코드 그대로에 입출력만 다르게 했더니 성공했다.

StringBuilder와 String의 차이에 대한 글을 포스팅까지 했는데 써먹지를 않았고 지난학기 자바 응용 수업에서 입출력스트림을 그렇게 많이, 자세히 배웠는데도 써먹지를 않은 나를 반성하게 되었다.

 

처음 짰던 그 코드에서 입출력하는 부분만 바꿔서

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {
    public static void main(String[] args) {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String s = "";
        StringBuilder sb = new StringBuilder();
        try {
            s = br.readLine();
        } catch (IOException e) {}
        StringTokenizer st = new StringTokenizer(s);
        int n = Integer.parseInt(st.nextToken());
        int m = Integer.parseInt(st.nextToken());
        int[] result = new int[m];
        permutationWithRepetition(n, m, 0, result, sb);
        System.out.println(sb);
    }
    static void permutationWithRepetition(int n, int m, int num, int[] result, StringBuilder sb) {
        if (num == m) {
            for (int i = 0; i < m; i++) {
                sb.append(result[i] + " ");
            }
            sb.append("\n");
            return;
        }
        for (int i = 0; i < n; i++) {
            result[num] = i + 1;
            permutationWithRepetition(n, m, num + 1, result, sb);
        }
    }
}

이렇게 제출했더니 성공했다.

 

괜히 쓸데없이 2시간을 버린 것 같아서 약간 허탈하지만 덕분에 매우 중요한 것을 알게 되었다.

1. Scanner, System.out.print()보다 InputStreamReader를 쓰는게 더 빠르다.

2. 문자열에 계속 + " " 이런식으로 append할 일이 많으면 StringBuilder를 쓰는 게 훨씬 빠르다.

(그 이유는

 

[Java] String, StringBuilder, StringBuffer의 차이점

자바에 문자열을 담을 수 있는 클래스로 String, StringBuilder, StringBuffer라는 클래스들이 있는데 약간씩 차이가 있다. 일단 가장 큰 차이점은 String은 문자열을 변경할 수 없지만 StringBuilder, StringBuff..

breakcoding.tistory.com

이 글을 보면 나와있다)

3. 줄바꿈을 하고 싶으면 System.out.println()을 쓰는게 아니라 StringBuilder에 "\n"을 계속 append 하고 줄마다 출력하는게 아니라 한번에 출력하는 것이 훨씬 빠르다. 

 

앞으로는 이런 헛수고 하지 않게 명심하자!

728x90

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

[백준] 9963번 N-Queen  (0) 2020.01.06
[백준] 15652번 N과 M (4)  (0) 2020.01.06
[백준] 15650번 N과 M (2)  (0) 2020.01.06
[백준] 15649번 N과 M (1)  (0) 2020.01.06
[백준] 14502번 연구소  (0) 2020.01.05
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

n, k를 입력받아 nCk의 모든 경우를 출력하는 코드이다.

import java.util.Scanner;

public class Combination {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int k = in.nextInt();
        boolean[] visited = new boolean[n];
        for (int i = 0; i < n; i++) {
            visited[i] = false;
        }
        int[] result = new int[k];
        combination(visited, n, k, 0, result);
    }

    static void combination(boolean[] visited, int n, int k, int num, int[] result) {
        if (num == k) {
            for (int i = 0; i < k; i++) {
                System.out.print(result[i] + " ");
            }
            System.out.println();
            return;
        }
        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(visited, n, k, num + 1, result);
                visited[i] = false;
            }
        }
    }
}

 

728x90

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

[알고리즘] 플로이드 (Floyd) 알고리즘  (0) 2020.02.08
[알고리즘] 순열 (Permutation)  (0) 2020.01.06
728x90

nPr의 모든 경우를 출력하는 코드이다.

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt(); //1부터 n까지의 숫자 중에서
        int r = in.nextInt(); //r개를 뽑는다
        boolean[] visited = new boolean[n];
        int[] selected = new int[r];
        for (int i = 0; i < n; i++) {
            visited[i] = false;
        }
        permutation(selected, visited, n, r, 0);
    }
    static void permutation(int[] selected, boolean[] visited, int n, int r, int num) {
        if (num == r) {
            for (int i = 0; i < r; i++) {
                System.out.print(selected[i] + " ");
            }
            System.out.println();
            return;
        }
        for (int i = 0; i < n; i++) {
            if(!visited[i]){
                visited[i] = true;
                selected[num] = i + 1;
                permutation(selected, visited, n, r, num + 1);
                visited[i] = false;
            }
        }
    }
}

permutation 함수의 매개변수인 num은 num번째 숫자를 정하는 것이다.

permutation 함수의 for문은 그 num번째 자리에 1부터 n까지의 숫자 중에 어떤 숫자를 넣을지 정하는 것이다.

728x90

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

[알고리즘] 플로이드 (Floyd) 알고리즘  (0) 2020.02.08
[알고리즘] 조합 (Combination)  (0) 2020.01.06
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

+ Recent posts