작성
·
29
0
퀘스트를 한개씩 풀며 str, int를 비교하고 가능하면 point를 받아 이를 str과 int에 분배하며 최대한 많이 푸는 문제 이해서
static int go (int STR, int INT) {
if(dp[STR][INT] != -1) return dp[STR][INT];
dp[STR][INT] = 0;
int point = 0;
ArrayList<Integer> list = new ArrayList<>();
for (int i=0; i<n; i++) {
if(arr[i][0] <= STR || arr[i][1] <= INT) {
if(!visited[i]) {
visited[i] = true;
for (int j=0; j<=arr[i][2]; j++) {
int a = Math.min(1000, STR +j);
int b = Math.min(1000, INT+arr[i][2]-j);
dp[a][b] = Math.max(dp[a][b], go(a, b)+1);
}
visited[i] = false;
}
}
}
return dp[STR][INT];
}
이렇게 풀어야한다고 생각합니다.
즉
1번 퀘스트가 현재 능력치로 해결 가능하면
1. 방문처리
2. 그 포인트로 str, int에 분배하면서 다시 재귀
2 -1 . 현재 퀘스트를 해결한 것이니 go()재귀 다녀온 결과의 +1 함
3. 방문처리 해제
하지만 이렇게 접근하면 정답이 안되더라구요
왜 이 코드가 불가능한지 궁금합니다.
그래서 강사님 코드가 더더욱 이해가 가지 않습니다.
제가 문제를 잘 못 이해한건가요?
현재 str, int에서 최대한 한번에 해결할 수 있는 것을 모아서 한번에 해결하고 그 포인트를 모아서 분배하는 방법이 이해가 가지 않습니다. 포인트 분배는 마음대로니까 str, int 모두 point 분배를 전혀 안한 경우를 포함한 경우라고 생각하면 될까요?
이해가 가지 않는 코드부분은
for(int i = 0; i < n; i++){
if(a[i].x <= STR || a[i].y <= INT){
ret++; // <-- 요부분과
if(!visited[i]){
visited[i] = true;
pnt += a[i].c; // <-- 요부분입니다
v.push_back(i);
}
}
}
답변 1
0
안녕하세요 ㅎㅎ
자바로 링크를 주셔서요... 자바는 원래 답변드리지 않습니다.
먼저 이전 질문사항에 대한 답변은 다음과 같습니다.
현재 str, int에서 최대한 한번에 해결할 수 있는 것을 모아서 한번에 해결하고 그 포인트를 모아서 분배하는 방법이 이해가 가지 않습니다.
포인트 분배는 마음대로니까 str, int 모두 point 분배를 전혀 안한 경우를 포함한 경우라고 생각하면 될까요?
-> 네 맞습니다. 다음과 같이 STR에 0을 투자했을 때도 판단합니다.
for(int p = 0; p <= pnt; p++){
int nextSTR = min(1000, STR + p);
int nextINT = min(1000, INT + pnt - p);
ret = max(ret, rpg(nextSTR, nextINT));
for(int i = 0; i < n; i++){
if(a[i].x <= STR || a[i].y <= INT){
ret++;
앞의 코드는 지금의 포인트로 깰 수 있는 퀘스트라면 해당 갯수를++ 합니다.
if(!visited[i]){
visited[i] = true;
pnt += a[i].c;
v.push_back(i);
}
이전 함수에서 방문을 안했는데 & 깰 수 있다면 -> 방문처리하면서 -> 해당 포인트를 추가합니다.
왜 시간초과가 날까요?
->
for (int i=0; i<n; i++) {
if(arr[i][0] <= STR || arr[i][1] <= INT) {
if(!visited[i]) {
visited[i] = true;
for (int j=0; j<=arr[i][2]; j++) {
int a = Math.min(1000, STR + j);
int b = Math.min(1000, INT+ arr[i][2]- j);
dp[STR][INT] = Math.max(dp[STR][INT], go(a, b)+1);
지금 보시면 go라는 함수를 너무 많이 호출합니다. go함수 하나에 n * pnt만큼 호출되게 됩니다. 이부분을 줄여주셔야 합니다.
그리고 코드가 틀리는 이유는 저렇게 하면 이 STR, INT라는 DP의 의미 = 이 힘과 지력이 있을 때의 최대 퀘스트 갯수가 들어가는 의미가 깨지게 됩니다.
STR, INT를 기반으로 -> 깰 수 있는 최대 퀘스트 갯수를 카운팅하는 로직이 들어가야 합니다.
그리고 죄송하지만 원래 C++외의 언어 코드에는 답변드리지 않습니다.
다음부터는 C++ 코드로 부탁드립니다.
감사합니다.
Java 언어이지만 기본적인 배열과 list만 사용해서 이해하는데 어려움이 없을 것 같아 그대로 올리겠습니다.
백준에 제출해보니 1%이후 시간초과라는 결과가 나왔습니다.
나머지 예제들은 정상으로 나오지만 예제 1번 같은 경우 답이 4이지만 5가 나옵니다.
링크 : https://www.acmicpc.net/source/85680487