회고

  • 칸에 쓰여진 수의 합의 최대.
  • 각 테트로미노는 연속된 4개의 칸으로 이루어진 도형
  • 즉, DFS 로 depth <= 4 까지 최댓값을 구하면 된다
  • ㅗ,ㅜ,ㅏ,ㅓ 테트로미노의 경우는 DFS로 불가능하므로 따로 구해야 함


풀이

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


문제

폴리오미노란 크기가 1×1인 정사각형을 여러 개 이어서 붙인 도형이며, 다음과 같은 조건을 만족해야 한다.

  • 정사각형은 서로 겹치면 안된다.
  • 도형은 모두 연결되어 있어야 한다.
  • 정사각형의 꼭짓점끼리 연결되어 있어야 한다. 즉, 변과 꼭짓점이 맞닿아있으면 안된다.

정사각형 4개를 이어 붙인 폴리오미노는 테트로미노라고 하며, 다음과 같은 5가지가 있다.

아름이는 크기가 N×M인 종이 위에 테트로미노 하나를 놓으려고 한다. 종이는 1×1 크기의 칸으로 나누어져 있으며, 각각의 칸에는 정수가 하나 쓰여 있다.

테트로미노 하나를 적절히 놓아서 테트로미노가 놓인 칸에 쓰여 있는 수들의 합을 최대로 하는 프로그램을 작성하시오.

테트로미노는 반드시 한 정사각형이 정확히 하나의 칸을 포함하도록 놓아야 하며, 회전이나 대칭을 시켜도 된다.

입력

첫째 줄에 종이의 세로 크기 N과 가로 크기 M이 주어진다. (4 ≤ N, M ≤ 500)

둘째 줄부터 N개의 줄에 종이에 쓰여 있는 수가 주어진다. i번째 줄의 j번째 수는 위에서부터 i번째 칸, 왼쪽에서부터 j번째 칸에 쓰여 있는 수이다. 입력으로 주어지는 수는 1,000을 넘지 않는 자연수이다.

출력

첫째 줄에 테트로미노가 놓인 칸에 쓰인 수들의 합의 최댓값을 출력한다.


소스

import java.util.Scanner;
 
/*
 * 테트로미노가 4개의 정사각형으로 이루어져 있으므로
 * 연속된 4개의 정사각형으로 만들 수 있는 모양은 테트로미노들 중 한개로 표현 가능 함
 * DFS로 depth 4번만 visit 하면서 최대값을 찾으면 됨
 * ㅗ,ㅜ,ㅏ,ㅓ 테트로미노의 경우는 DFS로 불가능하므로 따로 구해야 함
 * */
public class Main {
    public static int N;
    public static int M;
 
    public static boolean[][] visited;
    public static int[][] board;
 
    public static int[] xx = { 00, -11 };
    public static int[] yy = { -1100 };
 
    public static int dfs(int x, int y, int count) {
        if (count >= 5) {
            return 0;
        }
 
        int ans = 0;
        // 다음 노드 선택 (왼쪽, 오른쪽, 위, 아래)
        for (int n = 0; n < 4; n++) {
            int nx = x + xx[n];
            int ny = y + yy[n];
            if (0 <= nx && nx < N && 0 <= ny && ny < M && !visited[nx][ny]) {
                visited[nx][ny] = true;
                ans = Math.max(ans, dfs(nx, ny, count + 1) + board[x][y]);
                visited[nx][ny] = false;
            }
        }
 
        return ans;
    }
 
    public static int oau(int x, int y) {
        int ans = 0;
        // ㅗ모양
        if (x >= 1 && y >= 1 && y < M - 1)
            ans = Math.max(ans, board[x][y] + board[x - 1][y] + board[x][y - 1] + board[x][y + 1]);
        // ㅜ모양
        if (x < N - 1 && y >= 1 && y < M - 1)
            ans = Math.max(ans, board[x][y] + board[x + 1][y] + board[x][y - 1] + board[x][y + 1]);
        // ㅏ모양
        if (x < N - 1 && x >= 1 && y < M - 1)
            ans = Math.max(ans, board[x][y] + board[x + 1][y] + board[x - 1][y] + board[x][y + 1]);
        // ㅓ모양
        if (x < N - 1 && x >= 1 && y >= 1)
            ans = Math.max(ans, board[x][y] + board[x + 1][y] + board[x - 1][y] + board[x][y - 1]);
 
        return ans;
    }
 
    public static void main(String[] args) throws Exception {
        Scanner sc = new Scanner(System.in);
 
        N = sc.nextInt();
        M = sc.nextInt();
 
        board = new int[N][M];
        visited = new boolean[N][M];
 
        // 입력
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                board[i][j] = sc.nextInt();
            }
        }
 
        // board 한칸씩 순회하며 최대값 찾음
        int ans = 0;
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                visited[i][j] = true;
                ans = Math.max(ans, dfs(i, j, 1));
                ans = Math.max(ans, oau(i, j));
                visited[i][j] = false;
            }
        }
 
        System.out.println(ans);
 
        sc.close();
    }
}


'스터디 > 알고리즘 문제풀이' 카테고리의 다른 글

[백준 2098] 외판원 순회  (0) 2018.11.26
[백준 9376] 탈옥  (0) 2018.11.26
[백준 1495] 기타리스트  (0) 2018.11.26
[백준 1102] 발전소  (0) 2018.11.26
[백준 1126] 같은 탑  (0) 2018.11.26

회고

  • 전형적인 DP 문제.
  • dp[i] = max(dp[i-1] + v[i], dp[i-1] - v[i])  if, dp[i-1] + v[i] < M, 0< dp[i-1] - v[i])
  • 마지막 곡 의 dp[i] 값이 정답

풀이

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


문제

Day Of Mourning의 기타리스트 강토는 다가오는 공연에서 연주할 N개의 곡을 연주하고 있다. 지금까지 공연과는 다른 공연을 보여주기 위해서 이번 공연에서는 매번 곡이 시작하기 전에 볼륨을 바꾸고 연주하려고 한다.

먼저, 공연이 시작하기 전에 각각의 곡이 시작하기 전에 바꿀 수 있는 볼륨의 리스트를 만들었다. 이 리스트를 V라고 했을 때, V[i]는 i번째 곡을 연주하기 전에 바꿀 수 있는 볼륨을 의미한다. 항상 리스트에 적힌 차이로만 볼륨을 바꿀 수 있다. 즉, 현재 볼륨이 P이고 지금 i번째 곡을 연주하기 전이라면, i번 곡은 P+V[i]나 P-V[i] 로 연주해야 한다. 하지만, 0보다 작은 값으로 볼륨을 바꾸거나, M보다 큰 값으로 볼륨을 바꿀 수 없다.

곡의 개수 N과 시작 볼륨 S, 그리고 M이 주어졌을 때, 마지막 곡을 연주할 수 있는 볼륨 중 최댓값을 구하는 프로그램을 작성하시오. 모든 곡은 리스트에 적힌 순서대로 연주해야 한다.

입력

첫째 줄에 N, S, M이 주어진다. (1 ≤ N ≤ 100, 1 ≤ M ≤ 1000, 0 ≤ S ≤ M) 둘째 줄에는 각 곡이 시작하기 전에 줄 수 있는 볼륨의 차이가 주어진다. 이 값은 1보다 크거나 같고, M보다 작거나 같다.

출력

첫째 줄에 가능한 마지막 곡의 볼륨 중 최댓값을 출력한다. 만약 마지막 곡을 연주할 수 없다면 (중간에 볼륨 조절을 할 수 없다면) -1을 출력한다.



소스

import java.util.Arrays;
import java.util.Scanner;
 
public class Main {
    public static int N;
    public static int S;
    public static int M;
    public static int[] V;
    public static boolean[][] dp;
 
    public static void main(String[] args) throws Exception {
        Scanner sc = new Scanner(System.in);
 
        N = sc.nextInt();
        S = sc.nextInt();
        M = sc.nextInt();
 
        V = new int[N + 1];
        dp = new boolean[N + 1][M + 1];
 
        for (int i = 1; i <= N; i++) {
            V[i] = sc.nextInt();
        }
 
        for (int i = 0; i < N; i++) {
            Arrays.fill(dp[i], false);
        }
 
        // 초기값 설정
        dp[0][S] = true;
 
        for (int i = 1; i <= N; i++) {
            for (int v = 0; v <= M; v++) {
                if (dp[i - 1][v]) {
                    if (v + V[i] <= M) {
                        dp[i][v + V[i]] = true;
                    }
                    if (0 <= v - V[i]) {
                        dp[i][v - V[i]] = true;
                    }
                }
 
            }
        }
 
        int ans = -1;
        for (int v = 0; v <= M; v++) {
            if (dp[N][v]) {
                ans = Math.max(ans, v);
            }
        }
 
        System.out.println(ans);
 
        sc.close();
    }
}


'스터디 > 알고리즘 문제풀이' 카테고리의 다른 글

[백준 2098] 외판원 순회  (0) 2018.11.26
[백준 9376] 탈옥  (0) 2018.11.26
[백준 14500] 테트로미노  (0) 2018.11.26
[백준 1102] 발전소  (0) 2018.11.26
[백준 1126] 같은 탑  (0) 2018.11.26

회고

  • 최대/최소 구하는 문제는 DFS
  • 기저 조건은 적어도 P개의 발전소가 고장나 있지 않도록 고친다
  • 그렇다면, 3 개의 발전소가 고장나 있지 않은 상태는 다양하다
    • 1, 0, 0, 1, 1
    • 0, 1, 1, 1, 0
    • 0, 0, 1, 1, 1
    • ...
  • 따라서 고장나 있지 않은 발전소 상태를 bit 값으로 표현 (발전소 최대 16개, 2^16)
  • dp[n][bit]
  • 이를 memoization 한다


풀이


문제

은진이는 발전소에서 근무한다. 은진이가 회사에서 잠깐 잘 때마다, 몇몇 발전소가 고장이난다. 게다가, 지금 은진이의 보스 형택이가 은진이의 사무실로 걸어오고 있다. 만약 은진이가 형택이가 들어오기 전까지 발전소를 고쳐놓지 못한다면, 은진이는 해고당할 것이다.


발전소를 고치는 방법은 간단하다. 고장나지 않은 발전소를 이용해서 고장난 발전소를 재시작하면 된다. 하지만, 이때 비용이 발생한다. 이 비용은 어떤 발전소에서 어떤 발전소를 재시작하느냐에 따라 다르다.


적어도 P개의 발전소가 고장나 있지 않도록, 발전소를 고치는 비용의 최솟값을 구하는 프로그램을 작성하시오.


입력

첫째 줄에 발전소의 개수 N이 주어진다. N은 16보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에는 발전소 i를 이용해서 발전소 j를 재시작할 때 드는 비용이 주어진다. i줄의 j번째 값이 그 값이다. 그 다음 줄에는 각 발전소가 켜져있으면 Y, 꺼져있으면 N이 순서대로 주어진다. 마지막 줄에는 P가 주어진다. 비용은 50보다 작거나 같은 음이 아닌 정수이고, P는 0보다 크거나 같고, N보다 작거나 같은 정수이다.


출력

첫째 줄에 문제의 정답을 출력한다. 불가능한 경우에는 -1을 출력한다.


소스

import java.util.Arrays;
import java.util.Scanner;
 
public class Main {
    public static int N;
    public static int[][] dp;
    public static int[][] cost;
    public static int P;
 
    public static int minCost(int yCnt, int ySet) {
        // 만약 목표 갯수에 도달했으면 그만 찾음
        if (yCnt >= P) {
            return 0;
        }
 
        // memo 가 있으면 리턴
        if (dp[yCnt][ySet] >= 0) {
            return dp[yCnt][ySet];
        }
 
        // 엄청 큰 수로 초기화
        dp[yCnt][ySet] = 1000000000;
 
        for (int i = 0; i < N; i++) {
            if ((ySet & (1 << i)) == (1 << i)) { // i가 켜져있음
                for (int j = 0; j < N; j++) {
                    if (i == j || (ySet & (1 << j)) == (1 << j)) // j도 켜져있으면 스킵
                        continue;
 
                    // 켜져있지 않은 발전소를 찾아 다음 state 계산
                    dp[yCnt][ySet] = Math.min(dp[yCnt][ySet], minCost(yCnt + 1, ySet | (1 << j)) + cost[i][j]);
                }
            }
        }
 
        return dp[yCnt][ySet];
    }
 
    public static void main(String[] args) throws Exception {
        Scanner sc = new Scanner(System.in);
 
        N = sc.nextInt();
 
        dp = new int[N + 1][1 << 16];
        cost = new int[N][N];
 
        // init
        for (int i = 0; i <= N; i++) {
            Arrays.fill(dp[i], -1);
        }
 
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                cost[i][j] = sc.nextInt();
            }
        }
 
        char[] chars = sc.next().toCharArray();
        P = sc.nextInt();
 
        int ySet = 0;
        int yCnt = 0;
        for (int i = 0; i < chars.length; i++) {
            if (chars[i] == 'Y') {
                ySet |= (1 << i);
                yCnt++;
            }
        }
 
        int ans = minCost(yCnt, ySet);
 
        System.out.println(ans == 1000000000 ? -1 : ans);
        sc.close();
    }
 
}


'스터디 > 알고리즘 문제풀이' 카테고리의 다른 글

[백준 2098] 외판원 순회  (0) 2018.11.26
[백준 9376] 탈옥  (0) 2018.11.26
[백준 14500] 테트로미노  (0) 2018.11.26
[백준 1495] 기타리스트  (0) 2018.11.26
[백준 1126] 같은 탑  (0) 2018.11.26



회고

  • 어떤 값을 0번째부터 부터 하나씩 선택, 안선택 하는 문제는 DP 로 풀어야 함 (DFS)
  • 하지만 N 이 50이므로, recursive call 을 하게되면 stack overflow 발생..
    • memoization 이 필요
  • dp[사용한 조각 갯수][왼쪽 탑 높이][오른쪽 탑 높이] 이러면..
    • 50 * 500000 * 500000 헐
  • dp[N][diff] 로 푼다
  • dfs(n, diff) 아래 값 들 중 max
    1. dp[n][diff] 또는 
    2. dfs(n+1, diff)
    3. difs(n, arr[n] + diff)
    4. dfs(n , |diff - arr[n]|)

풀이

문제

홍준이는 N개의 직사각형 블록을 가지고 있다. 홍준이는 블록 위에 또다른 블록을 올려놓는 방식으로 탑을 만들 수 있다. 이때, 두 개의 탑을 만드는데, 이 두 탑의 높이가 같게 만드려고 한다. (각 탑은 적어도 한 개의 블록을 포함해야 한다) 홍준이는 되도록이면 탑의 높이를 최대로 하려고 한다. 그리고 모든 블록을 사용할 필요는 없다.

각 블록의 높이가 주어질 때, 홍준이가 만들 수 있는 탑의 높이의 최댓값을 출력하는 프로그램을 작성하시오.

입력

첫째 줄에 조각의 개수 N이 주어진다. N은 50보다 작거나 같은 자연수이다. 둘째 줄에 각 조각의 높이가 주어진다. 높이는 500,000보다 작거나 같은 자연수이고, 모든 조각의 높이의 합은 500,000을 넘지 않는다.

출력

첫째 줄에 문제의 정답을 출력한다. 불가능할 때는 -1을 출력한다.



소스

import java.util.Arrays; import java.util.Scanner; public class Main { public static int N; public static int[][] dp; public static int[] arr; public static int inf = 1 << 20; public static int search(int n, int diff) { if (diff > 250000) return -inf; if (N == n) { if (diff == 0) return 0; else return -inf; } if (dp[n][diff] != -1) return dp[n][diff]; // 아무 선택하지 않은 경우 dp[n][diff] = search(n + 1, diff); // 차이를 더 벌리는 경우 dp[n][diff] = Math.max(dp[n][diff], search(n + 1, diff + arr[n])); // 차이를 좁히는 경우 if (arr[n] > diff) { dp[n][diff] = Math.max(dp[n][diff], diff + search(n + 1, arr[n] - diff)); } else { dp[n][diff] = Math.max(dp[n][diff], arr[n] + search(n + 1, diff - arr[n])); } return dp[n][diff]; } public static void main(String[] args) throws Exception { Scanner sc = new Scanner(System.in); N = sc.nextInt(); dp = new int[N + 1][250001]; arr = new int[N + 1]; for (int i = 0; i < N; i++) { arr[i] = sc.nextInt(); Arrays.fill(dp[i], -1); } int ans = search(0, 0); System.out.println(ans > 0 ? ans : -1); sc.close(); } }


'스터디 > 알고리즘 문제풀이' 카테고리의 다른 글

[백준 2098] 외판원 순회  (0) 2018.11.26
[백준 9376] 탈옥  (0) 2018.11.26
[백준 14500] 테트로미노  (0) 2018.11.26
[백준 1495] 기타리스트  (0) 2018.11.26
[백준 1102] 발전소  (0) 2018.11.26

p.91 ~ p.126

반복문

알고리즘의 수행시간을 지배하는 것은 반복문

반복문의 수행 횟수는 입력의 크기에 대한 횟수로 표현


수행시간에 따른 알고리즘 분류

선형 시간 알고리즘

입력의 크기에 대비해 걸리는 시간을 그래프로 그리면 직선인 경우.

우리가 찾는 좋은 알고리즘.


선형 이하 시간 알고리즘

N을 계속 절반으로 나누는 일을 1이하가 될때까지 지속

lgN: 100,000 을 17번만 나누면 1에 도달 함

ex) 이진 탐색 알고리즘

  • 정렬이 필요 A[ ]
  • A[i-1] < x <= A[i]


다항 시간 알고리즘

반복문의 수행 횟수를 다항식으로 표현

대다수의 알고리즘에 해당


지수 시간 알고리즘

완전탐색 방식, 재귀호출을 통해 할지 말지 결정하는 알고리즘

ex) DFS

n 가지 경우, 모든 조합의 수 2ⁿ, 조합이 맞는지 여부 체크 m*n

∴ 재귀호출() 2ⁿ + isValid() m*n = mn2ⁿ

입력으로 주어지는 숫자의 갯수가 아닌 숫자의 값에 따라 지수시간이 될 수도 있음




시간 복잡도

시간복잡도가 높다

입력의 크기가 증가할 때 수행시간이 급격히 증가

시간복잡도가 낮다

입력의 크기가 증가해도 수행시간이 비슷



알고리즘 수행시간은 보통 최악의 시간을 측정



O 표기법 (Big-O Notation)

주어진 함수에서 가장 빨리 증가하는 항만을 남긴 채 나머지 다 버림



정렬 알고리즘

선택 정렬은 무조건 O(N²)

삽입 정렬은 O(N) ~ O(N²) 까지 입력에 따라 다름

∴ 대부분의 경우 삽이 정렬이 더 빠름

∴ 삽입 정렬은 O(N²) 정렬 중 가장 빠른 알고리즘



수행 시간 어림짐작하기

1초 ≒ 1억

ex)

N == 10,000

O(N³)X
O(N²)O
O(NlgN)O




알고리즘 선택에 따른 수행 시간 비교

문제) 1차원 배열 연속된 부분 구간의 합이 최대인 구간

완전 탐색: O(N³)

반복문 2개 + 메모이제이션: O(N²)

분할 정복 알고리즘: O(NlgN)

동적 계획법: O(N)

'스터디 > 알고리즘 정리' 카테고리의 다른 글

탐욕법  (0) 2018.12.02
동적 계획법 테크닉 (not yet)  (0) 2018.12.02
동적 계획법 문제 풀이 (not yet)  (0) 2018.12.02
동적 계획법  (0) 2018.12.01
분할 정복  (0) 2018.11.27
디어캣 캣폴이 드디어 도착했당ㅎㅎ (7월 30일)

그런데..그런데!
일주일도 채 되지않아.. (8월 5일)

헐?...헐!

당장 바니쉬 작업 고고
곰팡난 부분은 교환 완료 (8월 7일)


아이사랑 수성바니쉬가 좋대서 반광 500ml를 샀다


세번 덧칠하다보니
시간도 부족 바니쉬도 부족..
스텝 두개랑 해먹프레임밖에 못했음 ㅜㅜ



낼모레가 주말인데

인터넷주문 안되는데..

어카지ㄷㄷㄷㄷ



폭풍검색 후 근처 삼화페인트에서 아이생각 수성 우드바니쉬 900ml를 직구!

(온라인 주문은 배송비가 따로붙기때문에.. 가격은 비슷)

 무광을살까 유광을살까 고민하다가 유광을샀는데..
 너무 번쩍거린다ㅜㅜ


그래도.. 안한것보단 나으니께.. ...

(조낸사포질)하우스랑 스텝1개 폴 전체 칠하고나니 400ml정도 사용한듯

나머지는 잘담아 고이 모셔두었다ㅎㅎ

  



이제 좀 마음이 놓인다..ㅎㅎ
곰팡이, 먼지, 때들 물럿거라!



AngularJS 는 Google에서 개발된 JavaScript Framework로써 SPA(Single Page Application)을 개발할 때 유용한 프레임웤.







https://angularjs.org/




Start !

HTML 문서에서 공백은 spacebar를 아무리 눌러도 삽입되지 않는다.

 이때는 &nbsp  태그를 삽입하여 공백을 넣어준다.



예제

공백을 &nbsp;&nbsp;&nbsp; 삽입할 경우에는 &nbsp;&nbsp;&nbsp;&nbsp; nbsp 태그를 이용하여 &nbsp;&nbsp;&nbsp; 연속적으로 삽입합니다.

공백을     삽입할 경우에는      nbsp 태그를 이용하여     연속적으로 삽입합니다.


'WEB > HTML' 카테고리의 다른 글

날짜 animation  (0) 2014.11.03
page loading 시 scrolling  (0) 2012.08.19
HTML 태그 총정리  (0) 2012.08.15
HTML 페이지 프레임 나누기  (0) 2012.08.14
HTML에 웹폰트 적용하기  (0) 2012.08.12

+ Recent posts