문제 URL : https://www.acmicpc.net/problem/10835
10835번: 카드게임
첫 줄에는 한 더미의 카드의 개수를 나타내는 자연수 N(1 ≤ N ≤ 2,000)이 주어진다. 다음 줄에는 왼쪽 더미의 카드에 적힌 정수 A(1 ≤ A ≤ 2,000)가 카드 순서대로 N개 주어진다. 그 다음 줄에는 오
www.acmicpc.net
문제 접근법 :
문제는 어렵지 않은문제입니다. 애초에 백트래킹으로 풀수있는문제지만 n이
2000이니 시간초과라는건 당연하겠죠 그렇다면 메모이제이션 기법을 활용해서 dp로 시간복잡도를 최소화 하라는 뜻이 분명할테니 dp로 해결하면됩니다.
- 언제든지 왼쪽 카드만 통에 버릴 수도 있고 왼쪽 카드와 오른쪽 카드를 둘 다 통에 버릴 수도 있다. 이때 얻는 점수는 없다.
- 오른쪽 카드에 적힌 수가 왼쪽 카드에 적힌 수보다 작은 경우에는 오른쪽 카드만 통에 버릴 수도 있다. 오른쪽 카드만 버리는 경우에는 오른쪽 카드에 적힌 수만큼 점수를 얻는다.
- (1)과 (2)의 규칙에 따라 게임을 진행하다가 어느 쪽 더미든 남은 카드가 없다면 게임이 끝나며 그때까지 얻은 점수의 합이 최종 점수가 된다.
주어진 조건1,2번 조건대로 코딩하시면됩니다.
소스코드 :
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
|
//By 콩순이냉장고
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int n;
vector<int> v1, v2;
vector<vector<int>> dp;
void input() {
cin >> n;
v1.resize(n);
v2.resize(n);
dp = vector<vector<int>>(n, vector<int>(n, -1));
for (int i = 0; i < n; i++)
cin >> v1[i];
for (int i = 0; i < n; i++)
cin >> v2[i];
}
int dfs(int l=0,int r=0) {
if (l == n || r == n) return 0;//더이상 남은카드가 없는경우
int& res = dp[l][r];
if (res != -1)return res;
int sum = 0;
sum = dfs(l + 1, r); //1번조건 왼쪽카드만 버리는경우
sum = max(sum, dfs(l + 1, r + 1));//1번조건 양쪽카드 다버리는경우
if (v1[l] > v2[r])sum = max(sum, dfs(l, r + 1) + v2[r]);//2번조건 오른쪽카드가 작을때 오른쪽카드를 버리고 그점수를 합산하는경우
return res = sum;
}
void solve() {
cout << dfs() << "\n";
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
//freopen("input.txt", "r", stdin);
input();
solve();
}
|
cs |
궁금한점 혹은 모르는점 어떤질문이든 댓글은 언제나 환영입니다.
'백준' 카테고리의 다른 글
백준 1113 수영장 만들기 (0) | 2021.10.17 |
---|---|
백준 2666 벽장문의 이동 (0) | 2021.10.05 |
백준 16401 과자 나눠주기 (0) | 2021.10.05 |
백준 11066 파일 합치기 (0) | 2021.09.29 |
백준 6324 URLs (0) | 2021.09.01 |