KOI 보드 게임은 N장의 카드를 갖고 시작한다. 각각의 카드 앞면에는 1번부터 N번까지 번호가 순서대로 적혀 있고, 뒷면에는 빨간색(R), 녹색(G), 파란색(B) 중 하나의 색깔이 칠해져 있다.
항상 1번 마을로부터 시작하여 길이 연결되어 있는 이웃 마을로 이동해 가는데 한 번 이동할 때마다 갖고 있는 카드를 번호 순서대로 한 장씩 내야 한다. 각 길은 빨간색(R), 녹색(G), 파란색(B) 중 하나의 색깔이 칠해져 있는데 만약 내놓은 카드의 색깔과 길의 색깔이 일치하면 10점의 점수를 얻는다.
예를 들어 N이 5이고 1번부터 5번까지의 카드 색깔이 R, G, R, B, G이라고 하자. 지도가 <그림 1>과 같이 주어졌다고 할 때,
1번 마을에서 시작하여 2번 마을로 가면 길의 색깔과 1번 카드의 색깔이 R로 일치하므로 10점을 받게 된다. 다음 3번 마을로 가면 마찬가지로 길의 색깔과 2번 카드의 색깔이 G로 일치하므로 10점을 추가로 받게 된다. 이어 1번, 2번, 3번 마을로 이동하면 총 30점을 받는다. 하지만 1번 마을에서 시작하여 2번 마을을 거쳐 3번, 4번, 3번, 2번 마을로 이동하면 총 40점을 받게 된다.
갖고 있는 카드의 정보와 지도가 주어질 때 받을 수 있는 최대 점수를 출력하는 프로그램을 작성하시오.
첫째 줄에 카드의 수 N이 주어진다. 둘째 줄에 N장의 카드의 색깔이 번호 순서대로 빈칸을 사이에 두고 주어진다. 셋째 줄에는 마을의 수 M과 길의 수 K가 빈칸을 사이에 두고 주어진다. 이어 K개의 줄에 길의 정보가 주어진다. 길의 정보는 양 끝 마을의 번호를 나타내는 서로 다른 두 개의 자연수와 길의 색깔이 빈칸을 사이에 두고 주어진다. 두 마을을 잇는 길은 최대 1개이다. N은 1000이하의 자연수, M은 500이하의 자연수, K는 10000이하의 자연수이다. 카드의 색깔과 길의 색깔은 R, G, B중 하나이다.
첫째 줄에 보드 게임에서 받을 수 있는 최대 점수를 출력한다.
5
R G R B G
4 5
1 2 R
1 3 G
2 3 G
1 4 R
4 3 B
40
이 문제는 DP(다이나믹 프로그래밍) 알고리즘을 이용해서 풀 수 있었다. DP문제는 풀어도 풀어도 어려운 것 같다고 느꼈다.
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) throws Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
String[] input = br.readLine().split(" ");
char[] arr = new char[N];
for(int i=0; i<N; i++)
arr[i] = input[i].charAt(0);
input = br.readLine().split(" ");
int M = Integer.parseInt(input[0]);
int[][] dp = new int[N+1][M+1];
int K = Integer.parseInt(input[1]);
ArrayList<Pair>[] list = new ArrayList[M+1];
for(int i=1; i<=M; i++)
list[i] = new ArrayList<>();
for(int i=0; i<K; i++) {
input = br.readLine().split(" ");
int start = Integer.parseInt(input[0]);
int end = Integer.parseInt(input[1]);
char c = input[2].charAt(0);
list[start].add(new Pair(end, c));
list[end].add(new Pair(start, c));
}
for(int i=N-1; i>-1; i--) {
char color = arr[i];
for(int j=M; j>0; j--) {
int temp = 0;
for(Pair p : list[j]) {
temp = Math.max(temp, dp[i+1][p.next] + (color==p.color ? 10 : 0));
}
dp[i][j] = temp;
}
}
System.out.println(dp[0][1]);
}
public static class Pair {
int next;
char color;
public Pair(int next, char color) {
this.next = next;
this.color = color;
}
}
}