Dynamic Programming - GitDeveloperKim/DreamEach GitHub Wiki

์ •์˜

  • ๋‹ค์ด๋‚˜๋ฏน ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ ์ ˆํžˆ ์‚ฌ์šฉํ•˜์—ฌ ์ˆ˜ํ–‰ ์‹œ๊ฐ„ ํšจ์œจ์„ฑ์„ ๋น„์•ฝ์ ์œผ๋กœ ํ–ฅ์ƒ์‹œํ‚ค๋Š” ๋ฐฉ๋ฒ•

  • ์ด๋ฏธ ๊ณ„์‚ฐ๋œ ๊ฒฐ๊ณผ๋Š” ๋ณ„๋„์˜ ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์— ์ €์žฅํ•˜์—ฌ ๋‹ค์‹œ ๊ณ„์‚ฐํ•˜์ง€ ์•Š๋Š”๋‹ค

  • ๋‹ค์ด๋‚˜๋ฏน ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ๊ตฌํ˜„์€ ์ผ๋ฐ˜์ ์œผ๋กœ ๋‘๊ฐ€์ง€ ๋ฐฉ์‹์œผ๋กœ ๊ตฌ์„ฑ (bottom-up, top-down)

  • ๋‹ค์Œ์˜ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•  ๋•Œ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

  1. ์ตœ์  ๋ถ€๋ถ„ ๊ตฌ์กฐ (Optimal Substructure)
    • ํฐ ๋ฌธ์ œ๋ฅผ ์ž‘์€ ๋ฌธ์ œ๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ž‘์€ ๋ฌธ์ œ์˜ ๋‹ต์„ ๋ชจ์•„์„œ ํฐ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐ
  2. ์ค‘๋ณต ๋ถ€๋ถ„ ๋ฌธ์ œ (Overlapping Subproblem)
    • ๋™์ผํ•œ ์ž‘์€ ๋ฌธ์ œ๊ฐ€ ๋ฐ˜๋ณต์ ์œผ๋กœ ํ•ด๊ฒฐ

๋ฉ”๋ชจ์ด์ œ์ด์…˜ (memoization)

  • ํ•œ๋ฒˆ ๊ณ„์‚ฐํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์— ๋ฉ”๋ชจํ•˜๋Š” ๊ธฐ๋ฒ•
    • ๊ฐ™์€๋ฌธ์ œ๋ฅผ ๋‹ค์‹œ ํ˜ธ์ถœํ•˜๋ฉด ๋ฉ”๋ชจํ–ˆ๋˜ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ€์ ธ์˜ด
    • ๊ฐ’์„ ๊ธฐ๋กํ•ด ๋†“๋Š”๋‹ค๋Š” ์ ์—์„œ ์บ์‹ฑ(caching)

์ ํ™”์‹

  • ์ ํ™”์‹์ด๋ž€ ์ธ์ ‘ํ•œ ํ•ญ๋“ค ์‚ฌ์ด์˜ ๊ด€๊ณ„์‹

๋ƒ…์ƒ‰ ๋ฌธ์ œ

  • knapsack์€ ์—ฌ๋Ÿฌ ๋ฌผ๊ฑด์ด ์žˆ์„ ๋•Œ ํŠน์ •ํ•œ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š” ์กฐํ•ฉ์„ ๊ตฌํ•˜๋Š” ๋ฌธ์ œ๋ฅผ ์˜๋ฏธํ•œ๋‹ค
  • ์ตœ์ ์˜ ์›๋ฆฌ(Principle of Optimality) : ์–ด๋–ค ๋ฌธ์ œ์˜ ์ž…๋ ฅ ์‚ฌ๋ก€์˜ ์ตœ์ ํ•ด๊ฐ€ ๊ทธ ์ž…๋ ฅ ์‚ฌ๋ก€๋ฅผ ๋ถ„ํ• ํ•œ ๋ถ€๋ถ„ ์‚ฌ๋ก€์— ๋Œ€ํ•œ ์ตœ์ ํ•ด๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ์œผ๋ฉด, ๊ทธ ๋ฌธ์ œ์— ๋Œ€ํ•˜์—ฌ ์ตœ์ ์˜ ์›๋ฆฌ๊ฐ€ ์„ฑ๋ฆฝํ•œ๋‹ค.
  • dp[i][w] : ๋ฐฐ๋‚ญ์˜ ๋‚จ์€ ๋ฌด๊ฒŒ(ํ•œ๋„)๊ฐ€ w์ผ๋•Œ i๋ฒˆ์งธ ๋ณด์„(๋ฌผ๊ฑด)๊นŒ์ง€ ์‚ฌ์šฉํ•˜์—ฌ ์กฐํ•ฉ ๊ฐ€๋Šฅํ•œ ์ตœ๋Œ€ ๊ฐ€์น˜ํ•ฉ
  • ๋ณด์„์ด ์œ ํ•œํ•  ๋•Œ (0-1)
    -> if (j-w[i] < 0) : dp[i-1,w] // ์ฑ„์šธ ์šฉ๋Ÿ‰์ด ์—†์„ ๋•Œ i๋ฒˆ์งธ ๋ณด์„ ์•ˆ ๋„ฃ๊ณ  ์ด์ „ ๊ฐ’ ๊ฐ€์ ธ์˜ค๊ธฐ
    -> else(j-w[i] >=0) : max(value[i] + dp[i-1][j-w[i]] , dp[i-1][j]) // i ๋ฒˆ์งธ ๋ณด์„์„ ์•ˆ ๋„ฃ๊ณ  ๊ทธ๋Œ€๋กœ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ๊ณผ i๋ฒˆ์งธ ๋ณด์„์„ ๋„ฃ์„ ๋•Œ ๋น„๊ต
  • ๋ณด์„์ด ๋ฌดํ•œํ•  ๋•Œ
    -> ์ด์ „์— ์ฑ„์› ๋˜ ๊ฒƒ์— ๋‚ด ๋ฌด๊ฒŒ๋ฅผ ๋”ํ•œ ๊ฒƒ๊ณผ ์ด์ „์— ๊ตฌํ•œ ๊ฐ’๊ณผ ๋น„๊ตํ•˜์—ฌ ๊ฐ€์น˜๊ฐ€ ๋” ํฐ๊ฒƒ์„ ํƒํ•œ๋‹ค
    -> dp[i][j] = max(dp[i][j-1], dp[i][j-w[i]]+value[i]) // i๋ฒˆ์งธ ๋ณด์„์„ ์•ˆ์“ฐ๋Š” ๊ฒฝ์šฐ์™€ ์ด์ „ ๊ฐ’์— i๋ฒˆ์งธ ๋ณด์„์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ ๋น„๊ต
    click
    click
import java.util.Scanner;

public class Main {
	public static int N,K;
	public static int []w = new int[100000];
	public static int []v = new int[100000];
	public static int [][] d = new int [101][100001]; 
        // d[i,w] : i๊ฐœ์˜ ๋ณด์„์ด ์žˆ๊ณ  ๋ฐฐ๋‚ญ์˜ ๋ฌด๊ฒŒํ•œ๋„๊ฐ€ w์ผ๋•Œ ์ตœ์ ์˜ ์ด์ต
	
	public static void main(String[] args) {
		Scanner in = new Scanner (System.in);
		N = in.nextInt();  // ๋ณด์„์˜ ๊ฐœ์ˆ˜
		K = in.nextInt();  // ์ตœ๋Œ€ ์šฉ๋Ÿ‰
		
		for (int i = 1; i <= N; i++) {
			w[i] = in.nextInt();  // ๋ณด์„์˜ ๋ฌด๊ฒŒ
			v[i] = in.nextInt();  // ๋ณด์„์˜ ๊ฐ€์น˜
		}
				
		for (int i = 1; i <= N; i++) {
			for (int j = 1; j <= K; j++) {
				if (j-w[i] >= 0) {
					d[i][j] = Math.max(d[i-1][j],d[i-1][j-w[i]] + v[i]);
				} else {
					d[i][j] = d[i-1][j];
				}
			}
		}
		System.out.println(d[N][K]);
	}
}

ํ‰๋ฒ”ํ•œ๋ฐฐ๋‚ญ_๋ฐฑ์ค€12865

dp[i][j] (๋ฌด๊ฒŒ/๊ฐ’) dp[][1] dp[][2] dp[][3] dp[][4] dp[][5] dp[][6] dp[][7]
1๋ฒˆ๋ณด์„ (6/13) 0 0 0 0 0 13 13
2๋ฒˆ๋ณด์„ (4/8) 0 0 0 8 8 13 13
3๋ฒˆ๋ณด์„ (3/6) 0 0 6 8 8 13 14
4๋ฒˆ๋ณด์„ (5/12) 0 0 6 8 12 13 14

LIS (long increasing subsequence)


n = Integer.parseInt(br.readLine());
		
input = new int[n+1];
dp = new int [n+1];

st = new StringTokenizer(br.readLine(), " ");
for (int i = 1; i <= n; i++) {
	input[i] = Integer.parseInt(st.nextToken());
}
		
dp[1] = input[1];
int index = 1;

for (int i = 2; i <= n; i++) {
	if (dp[index] < input[i]) { 
		dp[++index] = input[i]; 
	} else {
		/*
		int j = 1;
		for (j = 1; j <= index;j++) {
			if (dp[j] >= input[i])
				break;
		}*/
		dp[lower_bound(1,index,input[i])] = input[i];
	}
}
		
sb.append(index+"\n");
  • lower bound

private static int lower_bound (int s, int e, int v) {
	while (s < e) {
		int mid = (s+e)/2;
                // v ์ฐพ๊ณ ์ž ํ•˜๋Š” ๊ฐ’, dp[mid] ๋ฐฐ์—ด์—์„œ ์ค‘์•™๊ฐ’
		if (v <= dp[mid]) {
			e = mid;
		} else {
			s = mid+1;
		}
	}
	return e;
}
  • upper bound

private static int upperBound(List data, int target) {
    int begin = 0;
    int end = data.size();
    
    while(begin < end) {
    	int mid = (begin + end) / 2;
        
        if(data.get(mid) <= target) {
        	begin = mid + 1;
        }
        else {
        	end = mid;
        }
    }
    return end;
}

LCS (Low Common Substring / Low Common Subsequence)

โš ๏ธ **GitHub.com Fallback** โš ๏ธ