본문 바로가기

PS(알고리즘 문제풀이) 관련 글/PS일지

2024-03-02

-돌 게임(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