https://www.algospot.com/judge/problem/read/TRIPATHCNT

 

algospot.com :: TRIPATHCNT

삼각형 위의 최대 경로 수 세기 문제 정보 문제 9 5 7 1 3 2 3 5 5 6 위 형태와 같이 삼각형 모양으로 배치된 자연수들이 있습니다. 맨 위의 숫자에서 시작해, 한 번에 한 칸씩 아래로 내려가 맨 아래

www.algospot.com

코드설명

동적계획법을 활용합니다.

 

이 문제는 이전에 삼각형 위의 최대 경로의 합을 이용하여 해결할 수 있습니다.

예로 들어,

아래의 삼각형이 주어졌다고 가정합니다.

9
5 7
1 3 2
3 5 5 6

삼각형의 최대경로의 합을 구하면, 아래와 같습니다.

아래의 최대경로의 합을 구하는 방법은,

:path(r, c) : (r, c)에서 맨 아래줄까지 내려가는 부분 경로의 최대합을 반환한다." 라는 함수를 정의하여 구할 수 있습니다.

24
13 15
6 8 8
3 5 5 6

이제 우리는 24가 나오는 경로의 개수가 몇개인지 구하면 됩니다.

이는 

"count(r, c) : (r, c)에서 맨 아래줄까지 내려가는 최대 경로의 수를 반환한다." 라는 함수를 정의하여 구할 수 있습니다.

이는 다음과 같은 점화식을 정의할 수 있습니다.

count(r, c) = count(y + 1, x) ( path(y+1, x) > path(y+1, x + 1) )

                    count(y + 1, x + 1) ( path(y + 1, x) < path(y + 1, x + 1) )

                    count(y + 1, x) + count(y + 1, x + 1) ( path(y + 1, x)  == path(y + 1, x + 1) )

위의 점화식을 사용하여 구할 수 있습니다.

 

코드

메모이제이션을 적용한 코드입니다.

package Main;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;
 
public class Main {
	public static int C, N, M, S;
	public static int answer = 0;
	public static String Num;
	public static int[][] cache, cache2;
	public static int[][] map;
	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		
		C = Integer.parseInt(st.nextToken());
		while(C-- >0) {
			st = new StringTokenizer(br.readLine());
			N = Integer.parseInt(st.nextToken());
			map = new int[N][N];
			cache = new int[N][N];
			cache2 = new int[N][N];
			
			for(int i=0;i<N;i++) {
				Arrays.fill(cache[i], -1);
				Arrays.fill(cache2[i], -1);
				st = new StringTokenizer(br.readLine());
				for(int j=0;j<=i;j++) {
					map[i][j] = Integer.parseInt(st.nextToken());
				}
			}
			
//			for(int i=0;i<N;i++) {
//				for(int j=0;j<=i;j++) {
//					System.out.print(map[i][j]);
//				}
//				System.out.println();
//			}
//			System.out.println();
			
			System.out.println(count(0, 0));
		}
		
	}
	
	
	//(r, c)에서 시작해서 맨 아랫줄까지 내려가는 경로 중 최대 경로의 개수를 반환한다.
	public static int count(int r, int c) {
		//기저사례 : 맨 아래줄에 도달한 경우
		if(r == N - 1) return 1;
		if(cache[r][c] != -1) return cache[r][c];
		
		int result = 0;
		if(path2(r + 1, c) >= path2(r + 1, c + 1)) result += count(r + 1, c);
		if(path2(r + 1, c)<= path2(r + 1, c + 1)) result += count(r + 1, c + 1);
		return cache[r][c] = result;
	}
	
	public static int path2(int r, int c) {
		if(r == N - 1) return map[r][c];
		if(cache2[r][c] != -1) return cache2[r][c];
		
		int result = 0;
		result = Math.max(path2(r + 1, c), path2(r + 1, c + 1)) + map[r][c];
		return cache2[r][c] = result;
	}
}

 

메모이제이션을 적용한 두번쨰 코드입니다.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {
	public static int C, N, M, S;
	public static int answer = 0;
	public static int[][] map, cache, countCache;
	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		
		C = Integer.parseInt(st.nextToken());
		while(C-- >0) {
			st = new StringTokenizer(br.readLine());
			N = Integer.parseInt(st.nextToken());
			map = new int[N][N];
			cache = new int[N][N];
			countCache = new int[N][N];
			for(int i=0;i<N;i++) {
				Arrays.fill(cache[i], -1);
				Arrays.fill(countCache[i], -1);
			}
			for(int i=0;i<N;i++) {
				st = new StringTokenizer(br.readLine());
				for(int j=0; j<=i;j++) {
					map[i][j] = Integer.parseInt(st.nextToken());
				}
			}
			
			System.out.println(count(0, 0));
		}
		
	}
	
	
	public static int count(int r, int c) {
		if(r == N-1) {
			return 1;
		}
		if(countCache[r][c] != -1) return countCache[r][c];
		
		int ret = 0;
		if( trianglePath(r + 1, c) >= trianglePath(r + 1, c + 1)) ret += count(r + 1, c);
		if( trianglePath(r + 1, c) <= trianglePath(r + 1, c + 1)) ret += count(r + 1, c + 1);
		return countCache[r][c] = ret;
	}
	
	public static int trianglePath(int r, int c) {
		if(r == N-1) {
			return map[r][c];
		}
		if(cache[r][c] != -1) return cache[r][c];
		
		int ret = 0;
		ret = Math.max( trianglePath(r + 1, c), trianglePath(r + 1, c + 1) ) + map[r][c];
		return cache[r][c] = ret; 
	}
	
	
}

+ Recent posts