백준 2294 - 동전 2

문제 링크

생각 및 접근

  • 동전의 가치가 주어지고, 여러번 골라서 그 가치의 합이 k원이 되게 하는 최소 동전의 갯수를 출력하고, k원을 만들 수 없다면 -1을 출력하는 문제다.
  • dp[i]
    • i원이 되게 하는 최소 동전의 갯수를 저장한다.
  • 동전을 총 n개 받는다고 하면, 1번 동전을 고려했을 때, 1~2번 동전을 고려했을 때, ... , 1~n번 동전을 고려했을 때를 탐색 한다. 즉, 동전을 하나씩 더 추가하면서 k원이 되게 하는 최소 동전의 갯수를 찾는 것이다.
  • 추가할 동전의 값을 coin이라고 하면, j-for문을 돌려서 기존 dp[j]의 값과 dp[j - coin]에 coin을 추가했을 때의 값을 비교한다. dp[j] = min(dp[j], dp[j - coin] + 1);
      for (int j = coin; j <= k; j++) {
          dp[j] = min(dp[j], dp[j - coin] + 1);
      }

코드

#include <bits/stdc++.h>
#define _MAX 2147000000
using namespace std;

int n, k, coin, dp[10001];

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);  cout.tie(NULL);

    cin >> n >> k;

    for (int i = 1; i <= k; i++) {
        dp[i] = _MAX;
    }

    for (int i = 1; i <= n; i++) {
        cin >> coin;
        for (int j = coin; j <= k; j++) {
            dp[j] = min(dp[j], dp[j - coin] + 1);
        }
    }

    if (dp[k] == _MAX)  cout << -1;
    else                cout << dp[k];
}

채점 결과

'Coding Test > acmicpc' 카테고리의 다른 글

백준 5557 - 1학년 (c++)  (0) 2020.08.24
백준 1495 - 기타리스트 (c++)  (0) 2020.08.24
백준 1904 - 01타일 (c++)  (0) 2020.08.19
백준 1699 - 제곱수의 합 (c++)  (0) 2020.08.16
백준 12865 - 평범한 배낭 (c++)  (0) 2020.08.15

백준 1904 - 01타일

문제 링크

생각 및 접근

  • 문제가 구구절절 길었지만, 결국엔 00과 1을 조합해서 n의 길이를 만들었을 때, 몇 개의 숫자를 만들 수 있는지 계산하는 문제였다.
  • dp[i]
    • 00과 1을 조합해서 i의 길이를 만들었을 때, 몇 개의 숫자를 만들 수 있는지 저장
    • 이전 값에서 00을 붙여서 길이가 i인 숫자를 만들 수 있는 경우 : dp[i - 2]
    • 이전 값에서 1을 붙여서 길이가 i인 숫자를 만들 수 있는 경우 : dp[i - 1]
    • ∴ dp[i] = dp[i - 2] + dp[i - 1]

코드

#include <bits/stdc++.h>
using namespace std;

int dp[1000001], n;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);  cout.tie(NULL);

    cin >> n;

    dp[1] = 1;  dp[2] = 2;

    for (int i = 3; i <= n; i++) {
        dp[i] = (dp[i - 1] + dp[i - 2]) % 15746;
    }

    cout << dp[n];
}

채점 결과

'Coding Test > acmicpc' 카테고리의 다른 글

백준 1495 - 기타리스트 (c++)  (0) 2020.08.24
백준 2294 - 동전 2 (c++)  (0) 2020.08.19
백준 1699 - 제곱수의 합 (c++)  (0) 2020.08.16
백준 12865 - 평범한 배낭 (c++)  (0) 2020.08.15
백준 1149 - RGB거리 (c++)  (0) 2020.08.15

백준 1699 - 제곱수의 합

문제 링크

생각 및 접근

  • dp[i]
    • i를 제곱수의 합으로 나타내었을 때 가질 수 있는 항의 최솟값을 저장한다.
  • 우선, dp[i]의 최솟값은 i가 제곱수일 때이므로 1이다. 필자는 cnt라는 변수를 사용해 내가 검사하려는 i가 제곱수인지 판별하였다.
      if (i == cnt * cnt) {
          dp[i] = 1;
          cnt++;
      }
  • i를 제곱수의 합으로 나타낼 때 가질 수 있는 항의 최솟값을 구하기 위해서는 일단 제곱수가 많을수록 유리하다. 따라서 제곱수가 하나 있다고 생각하고 j-for문을 돌렸다.
    • 18 = 16 + 1 + 1 = 9 + 9 인 경우도 있으므로, j-for문을 돌렸어야 했다.
        dp[i] = 2147000000;
        for (int j = 1; j <= cnt - 1; j++) {
            dp[i] = min(dp[i], 1 + dp[i - j * j]);
        }

코드

#include <bits/stdc++.h>
using namespace std;

int n, cnt = 1, dp[100001];

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);  cout.tie(NULL);

    cin >> n;
    for (int i = 1; i <= n; i++) {
        if (i == cnt * cnt) {
            dp[i] = 1;
            cnt++;
        }
        else {
            dp[i] = 2147000000;
            for (int j = 1; j <= cnt - 1; j++) {
                dp[i] = min(dp[i], 1 + dp[i - j * j]);
            }
        }
    }

    cout << dp[n];
}

채점 결과

'Coding Test > acmicpc' 카테고리의 다른 글

백준 2294 - 동전 2 (c++)  (0) 2020.08.19
백준 1904 - 01타일 (c++)  (0) 2020.08.19
백준 12865 - 평범한 배낭 (c++)  (0) 2020.08.15
백준 1149 - RGB거리 (c++)  (0) 2020.08.15
백준 15989 - 1, 2, 3 더하기 4 (c++)  (0) 2020.08.12

백준 12865 - 평범한 배낭

문제 링크

생각 및 접근

  • 전형적인 냅색 알고리즘이다.
  • dp[i]
    • 현재 배낭의 무게가 i일 때의 최대 가치를 저장
  • 배낭에 넣을 수 있는 물건이 중복되지 않으므로, j-for문을 역순으로 체킹하면 중복 없이 확인할 수 있다.
      for(int j = k; j >= w; j--){
          dp[j] = max(dp[j], dp[j - w] + v);
      }
    • k는 가방의 제한 무게, w는 현재 검사하려는 물건의 무게, v는 현재 검사하려는 물건의 가치
    • j-for문
      • j를 k부터 w까지 돌린다. j가 w보다 작은 값을 도는 것은 의미가 없다. 현재 검사하려는 물건의 무게가 w이므로, w 미만의 가방 무게에는 검사하려는 물건이 들어갈 수 없다.
      • dp[j]dp[j - w] + v 중 큰 값으로 dp[j]를 업데이트 한다.

코드

#include <bits/stdc++.h>
using namespace std;

int n, k, w, v, dp[100001];

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);  cout.tie(NULL);

    cin >> n >> k;
    for(int i = 1; i <= n; i++){
        cin >> w >> v;
        for(int j = k; j >= w; j--){
            dp[j] = max(dp[j], dp[j - w] + v);
        }
    }

    cout << dp[k];
}

채점 결과

'Coding Test > acmicpc' 카테고리의 다른 글

백준 1904 - 01타일 (c++)  (0) 2020.08.19
백준 1699 - 제곱수의 합 (c++)  (0) 2020.08.16
백준 1149 - RGB거리 (c++)  (0) 2020.08.15
백준 15989 - 1, 2, 3 더하기 4 (c++)  (0) 2020.08.12
백준 1890 - 점프 (c++)  (0) 2020.08.10

백준 1149 - RGB거리

문제 링크

생각 및 접근

  • 처음에 예제 입력 값이 무엇인지 헷갈렸지만, 각 집마다 색깔을 칠하는 가격이 달랐던 것이다.
  • dp[i][j]
    • i번째 집까지 색칠했고, i번째 집에는 j의 색깔로 칠했을 때 비용의 최솟값을 저장한다.
    • 색깔은 총 3가지고, 집의 범위는 1000개까지 이므로 dp[1001][3]로 선언하였다.
    • dp[i][0]를 구하려고 할 때, 이전 집(i - 1번째 집)에서 칠한 색깔은 1 또는 2여야 하므로 min(dp[i - 1][1] + arr[i][0], dp[i - 1][2] + arr[i][0]);와 같이 점화식을 세워볼 수 있겠다.
    • dp[i][1], dp[i][2]는 위와 동일한 방식으로 아래와 같은 점화식을 세울 수 있다.
      • dp[i][1] = min(dp[i - 1][0] + arr[i][1], dp[i - 1][2] + arr[i][1]);
      • dp[i][2] = min(dp[i - 1][0] + arr[i][2], dp[i - 1][1] + arr[i][2]);

코드

#include <bits/stdc++.h>
using namespace std;

int n, arr[1001][3], dp[1001][3];

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);  cout.tie(NULL);

    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> arr[i][0] >> arr[i][1] >> arr[i][2];
    }

    for (int i = 1; i <= n; i++) {
        dp[i][0] = min(dp[i - 1][1] + arr[i][0], dp[i - 1][2] + arr[i][0]);
        dp[i][1] = min(dp[i - 1][0] + arr[i][1], dp[i - 1][2] + arr[i][1]);
        dp[i][2] = min(dp[i - 1][0] + arr[i][2], dp[i - 1][1] + arr[i][2]);
    }

    cout << min({ dp[n][0], dp[n][1], dp[n][2] });
}

채점 결과

'Coding Test > acmicpc' 카테고리의 다른 글

백준 1699 - 제곱수의 합 (c++)  (0) 2020.08.16
백준 12865 - 평범한 배낭 (c++)  (0) 2020.08.15
백준 15989 - 1, 2, 3 더하기 4 (c++)  (0) 2020.08.12
백준 1890 - 점프 (c++)  (0) 2020.08.10
백준 11048 - 이동하기 (c++)  (0) 2020.08.10

백준 15989 - 1, 2, 3 더하기 4

문제 링크

생각 및 접근

  • 숫자 n을 1, 2, 3으로 더하되, 중복되지 않는 가짓수를 구하는 문제다.
  • 정수 i를 만들 때 오름차순으로만 더할 수 있다고 가정하고, dp[i][j]를 정수 i를 만들 때 마지막으로 더한 수가 j인 경우의 수를 저장하였다.
  • 정수 i를 만들 때의 case 분류
    • 기존 값에서 i를 만들기 위해 더할 수 있는 수가 1인 경우
      • 기존 값의 마지막 수가 1이 되어야 한다.
      • dp[i][1] = dp[i - 1][1];
    • 기존 값에서 i를 만들기 위해 더할 수 있는 수가 2인 경우
      • 기존 값의 마지막 수가 1 또는 2가 되어야 한다.
      • dp[i][2] = dp[i - 2][1] + dp[i - 2][2];
    • 기존 값에서 i를 만들기 위해 더할 수 있는 수가 3인 경우
      • 기존 값의 마지막 수가 1 또는 2 또는 3이 되어야 한다.
      • dp[i][3] = dp[i - 3][1] + dp[i - 3][2] + dp[i - 3][3];

코드

#include <bits/stdc++.h>
using namespace std;

int cases, n;
long long dp[10001][4];

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);  cout.tie(NULL);

    dp[1][1] = 1;
    dp[2][1] = 1;   dp[2][2] = 1;
    dp[3][1] = 1;   dp[3][2] = 1;   dp[3][3] = 1;
    for (int i = 4; i <= 10000; i++) {
        dp[i][1] = dp[i - 1][1];
        dp[i][2] = dp[i - 2][1] + dp[i - 2][2];
        dp[i][3] = dp[i - 3][1] + dp[i - 3][2] + dp[i - 3][3];
    }

    cin >> cases;
    while (cases--) {
        cin >> n;
        cout << dp[n][1] + dp[n][2] + dp[n][3] << endl;
    }
}

채점 결과

'Coding Test > acmicpc' 카테고리의 다른 글

백준 12865 - 평범한 배낭 (c++)  (0) 2020.08.15
백준 1149 - RGB거리 (c++)  (0) 2020.08.15
백준 1890 - 점프 (c++)  (0) 2020.08.10
백준 11048 - 이동하기 (c++)  (0) 2020.08.10
백준 2580 - 스도쿠 (c++)  (0) 2020.08.09

백준 1890 - 점프

문제 링크

생각 및 접근

  • 문제를 이해하는 것이 우선이였다. 내가 위치하는 곳의 값만큼 오른쪽이나 아래로 이동할 수 있다는 것이다.
  • 동적 프로그래밍을 이용해 풀었는데, dp[i][j]에 (i, j)로 왔을 때 경로의 수를 저장하였다.
    • 주황색 부분을 검사하는 코드가 다음과 같다. 주황색 부분을 돌면서, 주황색 부분에 든 숫자 arr[][]와 주황색과 [i][j]까지의 거리가 같다면, 주황색에서 [i][j]로 이동할 수 있다는 것을 알게 된다. 따라서, dp[i][j] += dp[k][j];를 해주면, 주황색 부분까지 가는 경우의 수를 더해준다는 의미가 되겠다.
        for (int k = 1; k < i; k++) {
            if (arr[k][j] == i - k) {
                dp[i][j] += dp[k][j];
            }
        }
    • 초록색 부분을 검사하는 코드가 다음과 같다. 초록색 부분을 돌면서, 주황색 부분에 든 숫자 arr[][]와 초록색과 [i][j]까지의 거리가 같다면, 초록색에서 [i][j]로 이동할 수 있다는 것을 알게 된다. 따라서, dp[i][j] += dp[i][k];를 해주면, 초록색 부분까지 가는 경우의 수를 더해준다는 의미가 되겠다.
        for (int k = 1; k < j; k++) {
            if (arr[i][k] == j - k) {
                dp[i][j] += dp[i][k];
            }
        }

코드

#include <bits/stdc++.h>
using namespace std;

int n;
long long arr[101][101], dp[101][101];

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);  cout.tie(NULL);

    cin >> n;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            cin >> arr[i][j];
        }
    }

    dp[1][1] = 1;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            for (int k = 1; k < i; k++) {
                if (arr[k][j] == i - k) {
                    dp[i][j] += dp[k][j];
                }
            }
            for (int k = 1; k < j; k++) {
                if (arr[i][k] == j - k) {
                    dp[i][j] += dp[i][k];
                }
            }
        }
    }

    cout << dp[n][n];
}

채점 결과

'Coding Test > acmicpc' 카테고리의 다른 글

백준 1149 - RGB거리 (c++)  (0) 2020.08.15
백준 15989 - 1, 2, 3 더하기 4 (c++)  (0) 2020.08.12
백준 11048 - 이동하기 (c++)  (0) 2020.08.10
백준 2580 - 스도쿠 (c++)  (0) 2020.08.09
백준 14502 - 연구소 (c++)  (0) 2020.08.07

백준 11048 - 이동하기

문제 링크

생각 및 접근

  • 아주 전형적인 동적 프로그래밍 문제
  • 값을 입력받을 배열 arr과 동적 프로그래밍 결과를 저장하는 배열 dp를 선언하였다.
  • dp[i][j]에는 (i, j)까지 탐색했을 때 가장 많은 사탕을 받을 수 있을 때, 가지고 있는 사탕의 수를 저장한다.
  • 준규는 (r, c)에 있으면, (r+1, c), (r, c+1), (r+1, c+1)로 갈 수 있으므로 위쪽 왼쪽부터 아래쪽 오른쪽 순서로 dp 탐색을 하면 될 것 같다. dp[i - 1][j] + arr[i][j], dp[i - 1][j - 1] + arr[i][j], dp[i][j - 1] + arr[i][j] 중에서 dp[i][j]에 가장 큰 값을 저장하면 된다.

코드

#include <bits/stdc++.h>
using namespace std;

int n, m, arr[1001][1001], dp[1001][1001];

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);  cout.tie(NULL);

    cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            cin >> arr[i][j];
        }
    }

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
            dp[i][j] = max(dp[i][j], dp[i - 1][j - 1]);
            dp[i][j] += arr[i][j];
        }
    }

    cout << dp[n][m];
}

채점 결과

'Coding Test > acmicpc' 카테고리의 다른 글

백준 15989 - 1, 2, 3 더하기 4 (c++)  (0) 2020.08.12
백준 1890 - 점프 (c++)  (0) 2020.08.10
백준 2580 - 스도쿠 (c++)  (0) 2020.08.09
백준 14502 - 연구소 (c++)  (0) 2020.08.07
백준 1759 - 암호 만들기 (c++)  (0) 2020.08.05

+ Recent posts