inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

10주완성 C++ 코딩테스트 | 알고리즘 코딩테스트

8-B

8-B 질문 있습니다.

95

tjd125gns

작성한 질문수 12

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);
            }
        }
	}

 

 

 

 

c++ 코딩-테스트

답변 1

0

큰돌

안녕하세요 ㅎㅎ

틀리신 전체 코드 부탁드립니다.(링크로 주시면 됩니다.)

 

감사합니다.

0

tjd125gns

Java 언어이지만 기본적인 배열과 list만 사용해서 이해하는데 어려움이 없을 것 같아 그대로 올리겠습니다.

백준에 제출해보니 1%이후 시간초과라는 결과가 나왔습니다.
나머지 예제들은 정상으로 나오지만 예제 1번 같은 경우 답이 4이지만 5가 나옵니다.

링크 : https://www.acmicpc.net/source/85680487

import java.util.*;
import java.io.*;

public class P1315 {
    static int n, arr[][], dp[][] = new int[1001][1001];
    static boolean visited[];
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        n = Integer.parseInt(br.readLine());
        arr = new int[n+1][3];
        visited = new boolean[n+1];

        for (int i=0; i<n; i++) {
            StringTokenizer st = new StringTokenizer(br.readLine());
            for (int j=0; j<3; j++) arr[i][j] = Integer.parseInt(st.nextToken());
        }

        for (int i=0; i<1001; i++)
            Arrays.fill(dp[i], -1);

        bw.write(go(1,1)+"");
        bw.flush();
        bw.close();
        br.close();
    }

    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[STR][INT] = Math.max(dp[STR][INT], go(a, b)+1);
                    }
                    visited[i] = false;
                }
            }
        }

        return dp[STR][INT];
    }
}

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++ 코드로 부탁드립니다.

 

감사합니다.

교안 158페이지 문의드립니다

0

3

1

코딩살구클럽 관련 건의사항

0

21

1

코살에 19942 다이어트 문제에 N의 범위가 빠져있슴니다

0

10

1

진행 방법 질문드립니다!

0

39

2

2-I) 왜 이 문제가 그래프이론 카테고리에 있는지 잘 모르겠습니다.

0

55

2

2주차 개념#12 트리 순회

0

25

2

백준사이트가 종료된다고 합니다.

0

286

2

백준 서비스 종료

9

887

1

sk 하이닉스 코테 대비

0

367

2

3-G 최댓값 질문

0

50

1

모듈러 연산 값이 10이 아닌 경우도 있지 않나요?

0

83

2

3-I 코드 질문드립니다.

0

62

2

3-N 질문 있습니다.

0

66

2

학습방법

0

102

2

4-H 질문 있습니다 (코드 리뷰)

0

66

2

코딩테스트 어디까지 준비해야 하는지 질문이 있습니다.

0

169

2

2-O 반례가 무엇일지 어떤 부분이 틀렸는지 잘 모르겠습니다.

0

69

2

2주차 개념 #4-2. 인접행렬 질문있습니다.

0

64

2

1-A 문제풀이 후 궁금한 점이 생겨서 질문드립니다.

0

51

2

조합 재귀 풀이 확인 해주시면 감사하겠습니다.

0

68

2

함수별 시간복잡도

0

73

2

3-h 질문입니다.

0

49

1

안녕하세요 선생님. 시간 복잡도 4번 질문있습니다.

0

53

2

1-I 문제 질문 드립니다.

0

76

2