Algorithm/Algorithm 문제 풀이

[BAE/<JOON> 문제풀이] 10835. 카드게임

폭풍저그머성찡 2020. 6. 8. 14:10

https://www.acmicpc.net/problem/10835

 

10835번: 카드게임

첫 줄에는 한 더미의 카드의 개수를 나타내는 자연수 N(1 ≤ N ≤ 2,000)이 주어진다. 다음 줄에는 왼쪽 더미의 카드에 적힌 정수 A(1 ≤ A ≤ 2,000)가 카드 순서대로 N개 주어진다. 그 다음 줄에는 오��

www.acmicpc.net

처음에 일반적인 n*n 포문으로 점화식 짜서 풀었다.

 

근데 자꾸 틀려서 코너케이스 찾다가 포기하고 답봤는데 바텀업 재귀 써서 푸는 문제였다.

 

답보고 생각해보니까 각 단계에 대해서 이전 단계는 (-1, -1)과 (-1, 0), (0, -1) + right[0] 세가지이므로

 

바텀업 재귀가 맞는 풀이였다. 왜 n*n포문으로 했는지 나도 모르겠다. 심지어 그렇게 푼 코드 코너케이스를 하나도 못찾아서 포기하고 정답찾아봄..

 

같은 티어여도 정올 출처 문제들은 훨씬 어려운거 같다..

더보기
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>

using namespace std;
int n;
int l[2005];
int r[2005];
int dp[2005][2005]; // 왼쪽 = 1 오른쪽 2일때 최적값

int cg(int lc, int rc) {
	if (lc >= n + 1 || rc >= n + 1) return dp[lc][rc] = 0;
	if (dp[lc][rc] != -1) return dp[lc][rc];
	int s3 = -1;
	if (l[lc] > r[rc]) s3 = cg(lc, rc + 1) + r[rc];
	int s1 = cg(lc + 1, rc);
	int s2 = cg(lc + 1, rc + 1);
	dp[lc][rc] = max({ s1, s2, s3 });
	return dp[lc][rc];
}

int main() {
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) {
		scanf("%d", l + i);
	}
	for (int i = 1; i <= n; i++) {
		scanf("%d", r + i);
	}
	for (int i = 0; i <= n + 1; i++) {
		for (int j = 0; j <= n + 1; j++) {
			dp[i][j] = -1;
		}
	}

	cout << cg(1, 1);

	return 0;
}

/*int main()
//{
//    int n;
//    scanf("%d", &n);
//    for (int i = 1; i <= n; i++) {
//        scanf("%d", &l[i]);
//    }
//    for (int i = 1; i <= n; i++) {
//        scanf("%d", &r[i]);
//    }
//    for (int i = 0; i <= n; i++) {
//        for (int j = 0; j <= n; j++) {
//            dp[i][j] = -1;
//        }
//    }
//    int mx = 0;
//    /*for (int i = 1; i <= n; i++) {
//        for (int j = 1; j <= n; j++) {
//            int s1 = dp[i - 1][j];
//            int s2 = dp[i - 1][j - 1];
//            int s3 = -1;
//            if (l[i] > r[j]) {
//                s3 = dp[i][j - 1] + r[j];
//            }
//            dp[i][j] = max({ s1, s2, s3 });
//            if (dp[i][j] > mx && (i == n || j == n) ) mx = dp[i][j];
//            if (dp[i - 1][j] == -1 && l[i] <= r[j]) break;            
//        }
//    }
//    dp[0][0] = 0;
//    for (int i = 0; i < n; i++) {
//        for (int j = 0; j < n; j++) {
//            dp[i + 1][j + 1] = max(dp[i + 1][j + 1], dp[i][j]);
//            dp[i + 1][j] = max(dp[i + 1][j], dp[i][j]);
//            if (l[i + 1] > r[j + 1]) {
//                dp[i][j + 1] = max(dp[i][j + 1], dp[i][j] + r[j + 1]);
//            }
//            
//        }
//    }
//    for (int i = 0; i <= n; i++) {      
//        if (dp[i][n] > mx) {
//            mx = dp[i][n];
//        }
//        if (dp[n][i] > mx) {
//            mx = dp[n][i];
//        }
//    }
//
//    /*for (int i = 0; i <= n; i++) {
//        for (int j = 0; j <= n; j++) {
//            cout << dp[i][j] << " ";
//        }
//        cout << "\n";
//    }
//    
//    cout << mx;
//    return 0;
//}*/