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

 

2240번: 자두나무

자두는 자두를 좋아한다. 그래서 집에 자두나무를 심어두고, 여기서 열리는 자두를 먹고는 한다. 하지만 자두는 키가 작아서 자두를 따먹지는 못하고, 자두가 떨어질 때까지 기다린 다음에 떨어

www.acmicpc.net

코드설명

 KnapSack(냅색, 배낭문제) + DP(Dynamic Programming) + 완전탐색(Brute Force) 를 활용하는 문제입니다.

 

문제에서 가장 중요한점은, 문제의 시간복잡도를 고려하는 것 입니다.

문제에서 총 탐색하는 횟수는 2가지의 W를 총 30번 선택하고, Level 은 1000 입니다. 2^30 의 가짓수가 나옵니다.

2^30 = 1,073,741,824, 10억입니다. 약 10초가 걸릴 것입니다.

 

그러모르 DP는 필수적입니다. DP[현재시각, 초][현재 선택횟수 W][몇번쨰 위치인가를

public static int[][][] dp = new int[1001][31][3];

이와 같이 표현합니다.

 

제가 실수했던 부분은 다음과 같습니다.

1. 자두의 위치는 처음에 1번 자두나무 아래에 위치해있다.

이 문제의 조건을 보고, 처음에 자두가 바로 위치를 바꾸는경우를 고려하지 못했습니다.무조건 1초에는 자두나무 1번에 있는것이 아닌, 1초에 W를 한번 사용해서 자두나무 2번에 있을 수 있습니다.이 부분에서 틀린 분들이 많을 것 같습니다.

answer = Math.max(simulate(0, 0, 1), simulate(0, 1, 2));

 

2. simulate함수 내에서 DP의 변수 잘못사용

아래의 코드가 맞지만 처음에는 dp[level][W][curPos]로 사용하여 당연히 틀렸었습니다. 

if(dp[level][curW][curPos] != -1)
    return dp[level][curW][curPos];

 

코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class Main {
	public static int N, M, P, T, W;
	public static int answer = 0;
	public static int[] jaduTree = new int[1001];
	public static int[][][] dp = new int[1001][31][3];
    public static void main(String[] args) throws IOException{
    	BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    	StringTokenizer st = new StringTokenizer(br.readLine());
    	
    	T = Integer.parseInt(st.nextToken());
    	W = Integer.parseInt(st.nextToken());
    	
    	for(int i=0;i<T;i++) {
    		st = new StringTokenizer(br.readLine());
    		jaduTree[i] = Integer.parseInt(st.nextToken()); 
//    		System.out.println("jaduTree[i]:"+jaduTree[i]);
    	}
    	
    	for(int i=0;i< 1001;i++) {
    		for(int j=0;j< 31;j++) {
    			for(int k=0;k<3;k++) {
    				dp[i][j][k] = -1;
    			}
    					
    		}
    	}
    	
    	answer = Math.max(simulate(0, 0, 1), simulate(0, 1, 2));
    	System.out.println(answer);
    	
    }
    
    public static int simulate(int level, int curW, int curPos) {
    	if(level == T) { //T번 떨어질경우 종료.
//    		System.out.println(sum);
//    		answer = Math.max(answer, sum);
    		return 0;
    	}
    	
    	if(dp[level][curW][curPos] != -1)
    		return dp[level][curW][curPos];
    	
    	//안움직이는경우
    	int temp1 = 0, temp2 = 0;
    	temp1 = ( jaduTree[level] == curPos ? 1 : 0 ) + simulate(level + 1, curW, curPos );
    	
    	//움직이는 경우
    	if(curW + 1 <= W)
    		temp2 = ( jaduTree[level] == curPos ? 1 : 0 ) + simulate(level + 1, curW + 1, curPos == 1 ? 2 : 1 );
    	
    	return dp[level][curW][curPos] = Math.max(temp1,  temp2);
    }
    
}

+ Recent posts