-
[백준 1315] RPG - DP알고리즘/코딩 테스트 2024. 2. 7. 10:57
https://www.acmicpc.net/problem/1315
시간 제한메모리 제한제출정답맞힌 사람정답 비율2 초 128 MB 4449 1126 735 25.026% 문제
준규는 새 RPG 게임을 시작했다. 이 게임에서 캐릭터는 2가지 스탯을 가지고 있다. 하나는 힘(STR)이고, 다른 하나는 지력(INT)이다. 캐릭터를 생성했을 때, 두 스탯은 모두 1이다.
게임에는 총 N개의 퀘스트가 있다. i번째 퀘스트를 깨려면 캐릭터의 힘이 STR[i]보다 크거나 같거나, 지력이 INT[i]보다 크거나 같아야 한다. 이 퀘스트를 깨면, 스탯을 올릴 수 있는 포인트를 PNT[i]개 만큼 얻게 된다.
모든 퀘스트는 단 한 번만 깰 수 있으며, 퀘스트를 깨는 순서는 준규가 마음대로 정할 수 있다. 또, 퀘스트 보상으로 얻게되는 포인트로 준규 마음대로 스탯을 올릴 수 있다.
준규가 깰 수 있는 퀘스트 개수의 최댓값을 구하는 프로그램을 작성하시오.
입력
첫째 줄에 퀘스트의 개수 N이 주어진다. N은 50보다 작거나 같은 자연수이다.
둘째 줄부터 N개의 줄에 STR[i], INT[i], PNT[i]가 주어진다. 이 숫자는 모두 1,000보다 작거나 같은 자연수이다.
출력
첫째 줄에 준규가 깰 수 있는 퀘스트 개수의 최댓값을 출력한다.
제한)n <= 500 <= STR[i], INT[i], PNT[i] <= 10002 초 128 MB
알고리즘)재귀 (1,1) 시작DP백트래킹...-> X
누락)퀘스트를 깨는 순서는 준규가 마음대로 정할 수 있다 ...-> 정렬!!XX순서 상관없음 -> for문으로 매번 확인!! -> visited
고난)시간.........!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!이 문제를 DP로 풀어야 하는 이유!!
- for 시간 최적화, 중복 계산을 방지
- if 재귀, 54 * 1000 * 1000 *54*1000 --> 시간초과!!
더보기int go(int visited, int STR, int INT){int ret = 0;
for (int j = 0; j < N; j++){if (!(visited & (1 << j)) && (STR >= S[j] || INT >= I[j])){for (int i = 0; i <= P[j]; i++){int newS = STR + i;int newI = INT + P[j] - i;if (newS > 1000 || newI > 1000)continue;ret = max(ret, go(visited | (1 << j), newS, newI) + 1);}}}
return ret;}How?
- STR,INT로 결과값을 얻을 수 있으므로 이 두 개를 DP로 저장하자!- 1,1 부터 시작해서 가능한 퀘스트에서 얻은 P를 합쳐서 다음으로 보내자- visited로 저장하고 ret = max(ret,go(new,new)) , visited = 0으로 초기화하자전체 코드
#include <bits/stdc++.h>using namespace std;int S[54], I[54], P[54], n, visited[54], dp[1004][1004];
int go(int STR, int INT){int &ret = dp[STR][INT];if (ret != -1)return ret;ret = 0;int p = 0;vector<int> temp;
for (int i = 0; i < n; i++){if (S[i] <= STR || I[i] <= INT){ret++;if (!visited[i]){p += P[i];visited[i] = 1;temp.push_back(i);}}}
for (int i = 0; i <= p; i++){int nextSTR = min(1000, STR + i);int nextINT = min(1000, INT + p - i);ret = max(ret, go(nextSTR, nextINT));}
for (int tt : temp){visited[tt] = 0;}return ret;}int main(){
ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
cin >> n;for (int i = 0; i < n; i++){cin >> S[i] >> I[i] >> P[i];}
memset(dp, -1, sizeof(dp));
cout << go(1, 1) << "\n";
return 0;}'알고리즘 > 코딩 테스트' 카테고리의 다른 글
[백준] 5397 키로거 - 연결리스트!! (0) 2024.02.16 [백준 1168] 요세푸스 문제 2 - 펜윅트리 응용 (0) 2024.02.08 [연결 리스트] 잦은 삽입 시 사용하는 알고리즘 (Feat. JAVA, C++) (1) 2024.02.06 [JS/ Node.js ] 백준 2588 문제 - 1의 자리수, 10의 자리수 , 100의 자리수 , 각 자리수 (0) 2023.08.16 [JS/ Node.js ] 백준 10171, 10172 문제 - 백틱, 백 슬래시 (0) 2023.08.16