ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 2024-03-02
    PS(알고리즘 문제풀이) 관련 글/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
Designed by Tistory.