-
2024-03-02PS(알고리즘 문제풀이) 관련 글/PS일지 2024. 3. 3. 00:01
-돌 게임(9655, 백준)
간단한 DP문제였다. 그냥 마지막 돌을 가져간 사람이 이김으로, 마지막 돌을 1로 두고 마지막 돌애서부터 1개 또는 3개 전의 돌을 가져가면 지게 됨으로 0으로 두는 식으로 점화식을 세우면 O(N)만에 풀 수 있다. 처음에는 수학적으로 접근하다가 N범위가 적은걸 보고 그냥 DP돌렸다. 수학으로도 풀린다는 소문이있다.
>점화식<
더보기if (dp[i + 1] == 0) dp[i] = 1;
else if (dp[i + 1] == 1) dp[i] = 0;
if (dp[i + 3] == 0) dp[i] = 1;
<소스코드>
더보기#include <stdio.h> int n; int dp[1010]; int main() { int i, j; scanf("%d", &n); dp[n] = 1; for (i = n - 1; i >= 1; i--) { if (dp[i + 1] == 0) dp[i] = 1; else if (dp[i + 1] == 1) dp[i] = 0; if (i <= n - 3) { if (dp[i + 3] == 0) dp[i] = 1; } } if (dp[1] == 1) printf("SK"); else printf("CY"); }
-기타 레슨(2343, 백준)
N범위 보고 문제보면 누가봐도 이분탐색문제이다. 숫자구슬이라는 문제랑 비슷하게 풀었던것같다. mid = 블루레이의 최대 용량으로 두고, 이때의 저장하기 위해 필요한 블루레이의 수를 mid_res로 두고, mid_res를 이용해 이분탐색을 진행 한뒤, 최소값을 구해야 함으로, low를 출력하면 된다.
<소스코드>
더보기#include <stdio.h> #include <algorithm> using namespace std; long long n, m; long long arr[100010]; long long pand(long long x) { long long i, ans = 0; long long s = 0; for (i = 0; i < n; i++) { if (s + arr[i] > x) { ans++; s = arr[i]; } else s += arr[i]; } return ans; } int main() { long long i, j; scanf("%lld %lld", &n, &m); long long low = -2e9, high = 0; for (i = 0; i < n; i++) { scanf("%lld", &arr[i]); high += arr[i]; if (low < arr[i]) low = arr[i]; } while (low <= high) { long long mid = (low + high) / 2; long long mid_res = pand(mid); if (mid_res < m) high = mid - 1; else low = mid + 1; } printf("%lld", low); return 0; }
-Coins(3067, 백준)
2차원 Dp문제였다. 어디선가 비슷한 문제를 푼 기억이 있는 것같은데, 기억은 안난다. Dp[i][j] = i종류까지의 동전만 이용해서 j원을 만드는 경우의 수로 풀었다. 1중 DP를 이용하면, 3 = 1 + 2, 3 = 2 + 1같이 겹치는 경우는 걸러내지 못해서, 2차원 Dp로 풀었다.
>점화식<
더보기dp[i][j] += dp[i - 1][j];
dp[i][j] += dp[i][j - vec[i]];
<소스코드>
더보기#include <stdio.h> #include <algorithm> #include <vector> using namespace std; int dp[30][10010]; int main() { int i, j; int t; scanf("%d", &t); while (t--) { int n; scanf("%d", &n); vector <int> vec; for (i = 0; i < n; i++) { int x; scanf("%d", &x); vec.push_back(x); } int m; scanf("%d", &m); for (i = 0; i < n; i++) { for (j = 1; j <= m; j++) { dp[i][j] = 0; } } for (i = 0; i < n; i++) { dp[i][vec[i]] = 1; for (j = 1; j <= m; j++) { if (i > 0) dp[i][j] += dp[i - 1][j]; if (j >= vec[i]) dp[i][j] += dp[i][j - vec[i]]; } } /*for (i = 0; i < n; i++) { for (j = 1; j <= m; j++) { printf("%d ", dp[i][j]); } printf("\n"); }*/ printf("%d\n", dp[n - 1][m]); } return 0; }
-가장 큰 정사각형(1915, 백준)
2차원 Dp문제였다. 정 사각형이 만들어지는 규칙을 찾아야 한다. Dp 테이블을 채워보며 Dp[i][j] = i, j까지탐색했을 때의 정사각형의 최대 변의 길이로 정의하면 된다.
>점화식<
더보기if (dp[i][j] == 1) dp[i][j] = min(dp[i - 1][j], min(dp[i - 1][j - 1], dp[i][j - 1])) + 1;
<소스코드>
더보기#include <stdio.h> #include <algorithm> using namespace std; int n, m; int dp[1010][1010]; int main() { int i, j; scanf("%d %d", &n, &m); for (i = 0; i < n; i++) { for (j = 0; j < m; j++) { scanf("%1d", &dp[i][j]); } } for (i = 1; i < n; i++) { for (j = 1; j < m; j++) { int mn = min(dp[i - 1][j], min(dp[i - 1][j - 1], dp[i][j - 1])); if (dp[i][j] == 1) dp[i][j] = mn + 1; } } int ans = -2e9; for (i = 0; i < n; i++) { for (j = 0; j < m; j++) { ans = max(dp[i][j], ans); } } printf("%d", ans*ans); return 0; }
-암호 코드(2011, 백준)
숫자카드 문제를 풀었던 기억이 있어 쉽게 풀었다. 사이에 끼인 0만 어떻게 처리해준다면 피보나치 수열과 비슷한 느낌이다.
>점화식<
더보기int x = s[i] - '0', y = s[i - 1] - '0';
if (x > 0) dp[i] = dp[i - 1];
if (y == 0) continue;
if (y * 10 + x <= 26) dp[i] = (dp[i] + dp[i - 2]);<소스코드>
더보기#include <stdio.h> #include <string.h> int n; int dp[5010]; char s[5010]; int main() { int i, j; scanf("%s", s + 1); s[0] = '0'; if (s[1] == '0') { printf("0"); return 0; } n = strlen(s) - 1; dp[0] = 1; dp[1] = 1; for (i = 2; i <= n; i++) { int x = s[i] - '0', y = s[i - 1] - '0'; if (x > 0) dp[i] = dp[i - 1]; if (y == 0) continue; if (y * 10 + x <= 26) dp[i] = (dp[i] + dp[i - 2]) % 1000000; } printf("%d", dp[n]); return 0; }
'PS(알고리즘 문제풀이) 관련 글 > PS일지' 카테고리의 다른 글
2024-03-04 (0) 2024.03.04 2024-03-03 (0) 2024.03.03 2024-03-01 (0) 2024.03.01 2024-02-29 (0) 2024.02.29 2024-02-28 (1) 2024.02.28