반응형

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

 

15489번: 파스칼 삼각형

첫째 줄에 양의 정수 R, C, W가 공백을 한 칸씩 두고 차례로 주어진다. (단, 2 ≤ R+W ≤ 30, 2 ≤ C+W ≤ 30, 1 ≤ W ≤ 29, C ≤ R)

www.acmicpc.net

<문제 풀이> 다이나믹 프로그래밍(DP), 수학

 

 

파스칼 삼각형을 아래 그림과 같이 왼쪽으로 정렬된 형태로 생각하면 2차원 배열로 쉽게 표현할 수 있습니다.

그러면 맨 왼쪽을 모두 1로 채운 뒤 ㄱ자 모양으로 파스칼 삼각형 DP 배열을 채우면 됩니다.

 

 

 

 

<C++소스코드>

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
#include<iostream>
#include<functional>
#include<algorithm>
using namespace std;
 
int R, C, W;
 
int dp[32][32];
 
int main() {
    ios_base::sync_with_stdio(false);
 
    cin >> R >> C >> W;
 
    for (int i = 1; i <= 31; i++) {
        dp[i][1= 1;
    }
 
    for (int i = 1; i <= 29; i++) {
        for (int j = 1; j <= 29; j++) {
            dp[i + 1][j + 1= dp[i][j] + dp[i][j + 1];
        }
    }
 
    int ans = 0;
 
    for (int i = 0; i < W; i++) {
        for (int j = 0; j <= i; j++) {
            ans += dp[R + i][C + j];
        }
    }
 
    cout << ans;
 
    return 0;
}
cs
반응형

'알고리즘 문제풀이 > 백준' 카테고리의 다른 글

[백준 20115번] 에너지 드링크  (0) 2023.04.22
[백준 1343번] 폴리오미노  (0) 2023.04.22
[백준 16953번] A -> B  (0) 2023.04.21
[백준 11508번] 2 + 1 세일  (0) 2023.04.20
[백준 1890번] 점프  (0) 2023.04.19
반응형

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

 

16953번: A → B

첫째 줄에 A, B (1 ≤ A < B ≤ 109)가 주어진다.

www.acmicpc.net

<문제 풀이>  BFS 알고리즘

 

큐에 다음 두 가지를 삽입하는 BFS를 구현하면 되는 문제입니다.

1. cur * 2 

2. cur * 10 + 1 

 

큐가 비워지기 전에 A == B가 되는 수를 찾으면 성공이고 큐가 비워졌을 때 A == B가 되는 수를 못 찾으면 실패입니다.

 

숫자 맨 뒤에 1을 추가하는 것은 2로 나누어 떨어지지 않기 때문에 숫자에 2를 곱한 것과 중복되지 않습니다.

따라서 방문 체크 배열을 만들 필요가 없습니다.

 

숫자는 최대 10^9이므로 2번 연산에서 10^9 * 10 + 1을 하면 int의 최대 크기를 넘어가기 때문에 long long 자료형을 사용해야 합니다.

 

 

<C++소스코드>

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
#include<iostream>
#include<queue>
#include<string>
#include<unordered_map>
#include<utility>
using namespace std;
 
#define X first
#define Y second
typedef long long ll;
 
ll A, B;
void bfs() {
    queue<pair<ll, ll> >Q;
    Q.push({A * 21}); //2를 곱한다.
    Q.push({A * 10 + 11}); // 1을 수의 가장 오른쪽에 추가한다.
    long long cnt = 0;
    while (!Q.empty()) {
        auto cur = Q.front(); Q.pop();
        if (cur.X == B) {
            cout << cur.Y + 1;
            return;
        }
        if (cur.X * 2 <= B) {
            Q.push({ cur.X * 2, cur.Y + 1 }); //2를 곱한다.
        }
        if (cur.X * 10 + 1 <= B) {
            Q.push({ cur.X * 10 + 1 , cur.Y + 1}); // 1을 수의 가장 오른쪽에 추가한다.
        }
    }
    cout << "-1";
}
 
int main() {
    ios_base::sync_with_stdio(false);
    cin >> A >> B;
 
    bfs();
    
 
    return 0;
}
cs
 

 

반응형

'알고리즘 문제풀이 > 백준' 카테고리의 다른 글

[백준 1343번] 폴리오미노  (0) 2023.04.22
[백준 15489번] 파스칼 삼각형  (0) 2023.04.21
[백준 11508번] 2 + 1 세일  (0) 2023.04.20
[백준 1890번] 점프  (0) 2023.04.19
[백준 1758번] 알바생 강호  (0) 2023.04.19
반응형

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

 

11508번: 2+1 세일

KSG 편의점에서는 과일우유, 드링킹요구르트 등의 유제품을 '2+1 세일'하는 행사를 하고 있습니다. KSG 편의점에서 유제품 3개를 한 번에 산다면 그중에서 가장 싼 것은 무료로 지불하고 나머지 두

www.acmicpc.net

<문제 풀이> 그리디 알고리즘

 

최대한 비싼 가격을 무료로 지불해야 하므로 내림차순으로 정렬해서 인덱스를 3으로 나누었을 때 나머지가 2인 가격을 무시하면 됩니다.

 

<C++소스코드>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<iostream>
#include<functional>
#include<algorithm>
using namespace std;
 
int n;
int c[100000];
 
int main() {
    ios_base::sync_with_stdio(false);
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> c[i];
    }
    sort(c, c + n, greater<int>());
    long long ans = 0;
    for (int i = 0; i < n; i++) {
        if (i % 3 == 2continue;
        ans += c[i];
    }
    cout << ans;
    return 0;
}
cs
 

 

반응형

'알고리즘 문제풀이 > 백준' 카테고리의 다른 글

[백준 15489번] 파스칼 삼각형  (0) 2023.04.21
[백준 16953번] A -> B  (0) 2023.04.21
[백준 1890번] 점프  (0) 2023.04.19
[백준 1758번] 알바생 강호  (0) 2023.04.19
[백준 13305번] 주유소  (0) 2023.04.19
반응형

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

 

1890번: 점프

첫째 줄에 게임 판의 크기 N (4 ≤ N ≤ 100)이 주어진다. 그 다음 N개 줄에는 각 칸에 적혀져 있는 수가 N개씩 주어진다. 칸에 적혀있는 수는 0보다 크거나 같고, 9보다 작거나 같은 정수이며, 가장

www.acmicpc.net

<문제 풀이> 다이나믹 프로그래밍(DP) 알고리즘

 

dp식을 아래와 같이 정의할 수 있습니다.

dp[i][j] : 가장 왼쪽 위 칸에서 시작해서 (i, j)까지 규칙에 맞게 이동할 수 있는 경로의 개수

 

(1, 1)은 처음 시작 위치이므로 (1,1)까지 이동할 수 있는 경로의 개수는 1입니다.

-> dp[1][1] = 1

 

dp[1][1]부터 dp[i][j]까지 dp 값이 잘 계산되었다고 생각하면

(i, j)에서 남쪽방향, 동쪽 방향의 dp값은 다음과 같이 계산할 수 있습니다.

 

남쪽 방향 = dp[i + arr[i][[j]] += dp[i][j];

동쪽 방향 = dp[i][j + arr[i][j]] += dp[i][j];

 

(i, j)까지 이동할 수 있는 경로의 개수를 알고 있다고 했을 때 다음 좌표로 점프하는 것은 (i, j)까지의 경로의 개수와 같습니다. 점프는 다른 경로로 생각하는 것이 아니라 같은 경로 이기 때문입니다.

그러나 다음 좌표로 점프하는 (i, j)가 여러 개가 존재하므로 단순히 대입하는 것이 아니라 dp[nx][ny]에 누적해야 합니다.

dp[i][j]값들은 가장 왼쪽 위 칸에서 시작해서 차례로 계산을 하기 때문에 잘 계산되어 있습니다.

 

한 가지 주의할 점은 경로의 개수는 문제에서 2^63 -1보다 작거나 같다고 했으므로 long long 배열을 선언해야 합니다.

 

<C++소스코드>

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
#include<iostream>
using namespace std;
 
int arr[101][101];
long long dp[101][101]; //dp[i][j] :가장 왼쪽 위 칸에서 시작해서 (i, j)까지 규칙에 맞게 이동할 수 있는 경로의 개수
 
const int dx[2= { 10 };
const int dy[2= { 01 };
 
int main() {
    ios_base::sync_with_stdio(false);
    int n;
    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++) {
            if (dp[i][j] == 0 || arr[i][j] == 0continue;
            for (int dir = 0; dir < 2; dir++) {
                int nx = i + dx[dir] * arr[i][j];
                int ny = j + dy[dir] * arr[i][j];
                if (nx < 1 || ny < 1 || nx > n || ny > n) continue;
                dp[nx][ny] += dp[i][j];
            }
 
        }
    }
    cout << dp[n][n];
 
    return 0;
}
cs
반응형
반응형

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

 

1758번: 알바생 강호

첫째 줄에 스타박스 앞에 서 있는 사람의 수 N이 주어진다. N은 100,000보다 작거나 같은 자연수이다. 둘째 줄부터 총 N개의 줄에 각 사람이 주려고 하는 팁이 주어진다. 팁은 100,000보다 작거나 같

www.acmicpc.net

<문제 풀이> 그리디, 정렬 알고리즘

 

팁 - (받은 등수 - 1)

 

위 식을 계산했을 때 0보다 작은 경우는 팁을 누적하지 않습니다.

전체 팁의 합을 최댓값으로 만드는 최적의 해는 사람을 배치할 때 팁을 적게 주는 사람을 최대한 뒤로 보내는 것입니다.

 

예를 들어

50원을 주는 사람이 1등이고, 10원을 주는 사람이 100등이라고 할 때 팁은 다음과 같이 계산됩니다.

 

50 - (1 - 1) = 50
10 -(100 -1 ) = 0

총 팁 : 50

 

50원을 주는 사람을 100등, 10원을 주는 사람을 1등이라고 할 때 팁은 다음과 같이 계산됩니다.

50 - (100 - 1) == 0

10 - (1 - 1) = 10

총 팁: 10

 

위 예시를 보면 뒤에 오는 사람은 식의 값이 0보다 작게 되어서 팁을 누적하지 않습니다.

둘 중에 한 명의 팁을 누적하지 않을 거라면 최대한 팁을 적게 주는 사람을 뒤로 보내 누적하지 않는 것이 최적의 해가 되는 것을 알 수 있습니다.

 

따라서 팁을 기준으로 내림차순 정렬한 뒤 식의 값을 누적하면 됩니다.

 

<C++소스코드>

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
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
 
typedef long long ll;
 
int seq[100001];
 
int main() {
    ios_base::sync_with_stdio(false);
 
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> seq[i];
    }
    sort(seq, seq + n, greater<int>());
    ll ans = 0;
    for (int i = 0; i < n; i++) {
        int m = seq[i] - i;
        if (m < 0continue;
        ans += m;
    }
    cout << ans;
    return 0;
}
cs
 

 

반응형
반응형

문제 링크: 

<문제 풀이> 그리디 알고리즘

 

현재까지 발견한 가격들 중 최소의 주유 가격으로 다음 최소 주유 가격을 발견할 때까지 이동하는 것을 반복하면 그것이 최적의 해가 됩니다.

 

위 그림에서

 

최솟값 5에서 다음 최솟값을 갱신할 때까지 이동하면 다음 위치는 2

최솟값 2에서 다음 최솟값을 갱신할 때까지 이동하면 다음 위치는 1

 

구현할 때는 바로 다음 위치까지 이동하는 것이 아닌 도시를 하나씩 방문하면 됩니다.

방문할 때마다 현재까지 발견한 가격들 중 최소의 주유 가격을 임시 변수에 저장하고 있어야 합니다.

현재 도시에서 다음 도시로 이동할 때 드는 비용은 (최솟값*거리)가 됩니다.

 

<C++소스코드>

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
#include<iostream>
#include<algorithm>
using namespace std;
 
typedef long long ll;
 
int n;
ll price[100000];
ll dist[100000];
int main() {
    ios_base::sync_with_stdio(false);
 
    cin >> n;
    for (int i = 0; i < n - 1; i++) {
        cin >> dist[i];
    }
    for (int i = 0; i < n; i++) {
        cin >> price[i];
    }
 
    ll ans = price[0* dist[0]; //처음에는 기름을 모두 넣고 다음 도시까지 간다.
    ll cur = price[0]; //현재까지 방문한 도시들의 주유 가격 중 최솟값
    for (int i = 1; i < n - 1; i++) {
        if (price[i] >= cur) { // 더 작은 주유 값을 발견하지 못하면
            ans += dist[i] * cur; // 현재까지 방문한 주유 최솟값으로 다음 도시로 이동
        }
        else { // 더 작은 주유 값을 발견하면
            cur = price[i]; // 최솟값 갱신
            ans += dist[i] * cur; // 최소 주유 값으로 다음 위치까지 이동
        }
    }
    cout << ans;
    return 0;
}
cs
 

 

반응형
반응형

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

 

11055번: 가장 큰 증가하는 부분 수열

수열 A가 주어졌을 때, 그 수열의 증가하는 부분 수열 중에서 합이 가장 큰 것을 구하는 프로그램을 작성하시오. 예를 들어, 수열 A = {1, 100, 2, 50, 60, 3, 5, 6, 7, 8} 인 경우에 합이 가장 큰 증가하는

www.acmicpc.net

<문제 풀이> 다이나믹 프로그래밍(DP) 알고리즘

 

기본적인 LIS 알고리즘을 구현하면 되는 문제입니다.

 

dp는 아래와 같이 정의할 수 있습니다.

 

dp[i] : i 번째까지의 원소를 고려했을 때 가장 큰 증가하는 부분 수열 중에서 합이 가장 큰 것

 

dp[i]를 갱신하는 방법은 1부터 i -1까지의 dp[j]에 각각에 대해 i 번째 원소를 포함했을 때 그 합이 가장 큰 것으로 갱신해 주면 됩니다.

 

dp[1] + seq[i] : 1 번째까지의 원소를 고려했을 때 가장 큰 증가하는 부분 수열 중에서 합이 가장 큰 것 + i 번째 원소의 값

dp[2]  + seq[i]: 2 번째까지의 원소를 고려했을 때 가장 큰 증가하는 부분 수열 중에서 합이 가장 큰 것 + i 번째 원소의 값

.

.

dp[j] + seq[i] : j 번째까지의 원소를 고려했을 때 가장 큰 증가하는 부분 수열 중에서 합이 가장 큰 것

.

.

dp[i - 1] + seq[i] : i -1 번째까지의 원소를 고려했을 때 가장 큰 증가하는 부분 수열 중에서 합이 가장 큰 것

 

 

	for (int i = 1; i <= n; i++) {
		dp[i] = seq[i]; // 처음에는 자기 자신만 고려
		for (int j = 1; j < i; j++) {
			if (seq[i] <= seq[j]) continue;
			dp[i] = max(dp[i], dp[j] + seq[i]);
		}
	}

 

 

 

 

 

<C++소스코드>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include<iostream>
#include<algorithm>
using namespace std;
 
int n;
int dp[1001];
int seq[1001];
int main() {
    ios_base::sync_with_stdio(false);
 
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> seq[i];
    }
    for (int i = 1; i <= n; i++) {
        dp[i] = seq[i]; // 처음에는 자기 자신만 고려
        for (int j = 1; j < i; j++) {
            if (seq[i] <= seq[j]) continue;
            dp[i] = max(dp[i], dp[j] + seq[i]);
        }
    }
    cout << *max_element(dp, dp + n + 1);
    return 0;
}
cs
 

 

반응형

'알고리즘 문제풀이 > 백준' 카테고리의 다른 글

[백준 1758번] 알바생 강호  (0) 2023.04.19
[백준 13305번] 주유소  (0) 2023.04.19
[백준 14916번] 거스름돈  (0) 2023.04.12
[백준 9465번] 스티커  (2) 2023.04.12
[백준 17626번] Four Squares  (0) 2023.04.12
반응형

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

 

14916번: 거스름돈

첫째 줄에 거스름돈 액수 n(1 ≤ n ≤ 100,000)이 주어진다.

www.acmicpc.net

<문제 풀이> 그리디 알고리즘

 

숫자가 큰 동전은 최대한으로 사용하고 숫자가 작은 동전은 최소한으로 사용하는 것이 최적의 해가 됩니다.

 

N이 5로 나누어 떨어질 때까지 N에서 2를 한 번씩 빼보는 것을 반복하면 됩니다.

 

N이 5로 나누어 떨어지면 그 몫은 5원 동전의 총 개수

N에서 2를 한 번 빼면 2원 동전 하나 사용

 

 

 

 

<C++소스코드>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include<iostream>
using namespace std;
 
int main(){
    ios_base::sync_with_stdio(false);
 
    int n;
    int ans = 0;
    cin >> n;
    while (n > 0) {
        if (n % 5 == 0) {
            ans += n / 5;
            n /= 5;
            break;
        }
        else {
            n -= 2;
            ans++;
        }
    }
    if (n < 0)cout << -1;
    else cout << ans;
    return 0;
}
cs
 

 

반응형

+ Recent posts