Hayden's Archive
[알고리즘] 백준 - 다이나믹 프로그래밍 관련 문제 3 본문
알고리즘 문제 출처 : 백준 - 15988번 : 1, 2, 3 더하기 3 https://www.acmicpc.net/problem/15988
내가 작성한 코드
import java.util.Scanner;
public class Main {
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
long[] check = new long[1000001];
check[1] = 1;
check[2] = 2;
check[3] = 4;
for(int i=4; i<check.length; i++) {
check[i] = check[i-1] + check[i-2] + check[i-3];
check[i] %= 1000000009;
}
for(int i=0; i<t; i++) {
int n = sc.nextInt();
System.out.println(check[n]);
}
}
}
알고리즘 문제 출처 : 백준 - 1149번 : RGB거리 https://www.acmicpc.net/problem/1149
내가 작성한 코드
import java.util.Scanner;
public class Main {
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[][] price = new int[n+1][3]; //각 집마다의 RGB 비용
int[][] total = new int[n+1][3]; //RGB 최소 비용합
for(int i=1; i<=n; i++) {
price[i][0] = sc.nextInt(); //R 비용
price[i][1] = sc.nextInt(); //G 비용
price[i][2] = sc.nextInt(); //B 비용
}
/* 1번 집까지의 RGB 비용 총합 초기화 */
total[1][0] = price[1][0];
total[1][1] = price[1][1];
total[1][2] = price[1][2];
for(int i=2; i<=n; i++) {
total[i][0] = Math.min(total[i-1][1], total[i-1][2]) + price[i][0];
total[i][1] = Math.min(total[i-1][0], total[i-1][2]) + price[i][1];
total[i][2] = Math.min(total[i-1][1], total[i-1][0]) + price[i][2];
}
int min = Math.min(Math.min(total[n][0], total[n][1]), total[n][2]);
System.out.println(min);
}
}
알고리즘 문제 출처 : 백준 - 1309번 : 동물원 https://www.acmicpc.net/problem/1309
내가 작성한 코드
import java.util.Scanner;
public class Main {
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[][] check = new int[n+1][3];
check[1][0] = 1;
check[1][1] = 1;
check[1][2] = 1;
int divisor = 9901;
for(int i=2; i<=n; i++) {
check[i][0] = (check[i-1][0] + check[i-1][1] + check[i-1][2]) % divisor;
check[i][1] = (check[i-1][0] + check[i-1][2]) % divisor;
check[i][2] = (check[i-1][0] + check[i-1][1]) % divisor;
}
System.out.println((check[n][0] + check[n][1] + check[n][2]) % divisor);
}
}
알고리즘 문제 출처 : 백준 - 11057번 : 오르막 수 https://www.acmicpc.net/problem/11057
내가 작성한 코드
import java.util.Scanner;
public class Main {
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[][] check = new int[n+1][10];
for(int i=0; i<10; i++) {
check[1][i] = 1;
}
int divisor = 10007;
for(int i=2; i<=n; i++) {
for(int j=0; j<10; j++) {
for(int l=j; l<10; l++) {
check[i][j] += (check[i-1][l]) % divisor;
}
}
}
int answer = 0;
for(int i=0; i<10; i++) {
answer += check[n][i];
answer %= divisor;
}
System.out.println(answer);
}
}
알고리즘 문제 출처 : 백준 - 9465번 : 스티커 https://www.acmicpc.net/problem/9465
내가 작성한 코드
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
for(int i=0; i<n; i++) {
int m = sc.nextInt();
long[][] sticker = new long[m+1][3]; //위쪽 스티커 1, 아래쪽 스티커 2
/* 스티커별 점수 초기화 */
for(int j=1; j<=m; j++) { //위쪽 스티커
sticker[j][1] = sc.nextInt();
}
for(int j=1; j<=m; j++) { //아래쪽 스티커
sticker[j][2] = sc.nextInt();
}
/* check 배열 선언 및 앞쪽값 일부 할당 */
long[][] check = new long[m+1][3];
for(int j=1; j<=m; j++) {
/* j번째 자리에 스티커를 떼지 않은 경우 */
check[j][0] = Math.max(Math.max(check[j-1][0], check[j-1][1]), check[j-1][2]);
/* j번째 위쪽 자리에서 스티커를 뗀 경우 */
check[j][1] = Math.max(check[j-1][0], check[j-1][2]) + sticker[j][1];
/* j번재 아래쪽 자리에서 스티커를 뗀 경우 */
check[j][2] = Math.max(check[j-1][0], check[j-1][1]) + sticker[j][2];
}
System.out.println(Math.max(Math.max(check[m][0], check[m][1]), check[m][2]));
}
}
}
알고리즘 문제 출처 : 백준 - 2156번 : 포도주 시식 https://www.acmicpc.net/problem/2156
내가 작성한 코드
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] wine = new int[n+1];
int[][] check = new int[n+1][3];
for(int i=1; i<=n; i++) {
wine[i] = sc.nextInt();
}
/* check[i][0] i번째 포도주를 마시지 않은 경우
* (i-1번째 포도주를 마시지 않았거나, 마셨거나, 2번 연속으로 마셨거나)
* check[i][1] i번째 포도주를 1번 연속으로 마신 경우
* (i-1번째 포도주를 마시지 않음)
* check[i][2] i번째 포도주를 2번 연속으로 마신 경우
* (i-1번째 포도주를 마심)
*/
check[1][0] = 0;
check[1][1] = wine[1];
check[1][2] = wine[1];
for(int i=2; i<=n; i++) {
check[i][0] = Math.max(Math.max(check[i-1][0], check[i-1][1]), check[i-1][2]);
check[i][1] = check[i-1][0] + wine[i];
check[i][2] = check[i-1][1] + wine[i];
}
System.out.println(Math.max(Math.max(check[n][0], check[n][1]), check[n][2]));
}
}
알고리즘 문제 출처 : 1932번 : 정수 삼각형 https://www.acmicpc.net/problem/1932
내가 작성한 코드
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[][] tri = new int[n][n]; //입력값을 받는 배열
int[][] sum = new int[n][n]; //n행 n열에서의 최대합
/* 입력값을 받음 */
for(int i=0; i<n; i++) {
for(int j=0; j<=i; j++) {
tri[i][j] = sc.nextInt();
}
}
/* 최대합 배열 0행 0열 초기화 */
sum[0][0] = tri[0][0];
/* 최대합을 구해서 배열에 할당한다.
* 점화식을
* sum[i][j] = Math.max(sum[i-1][j-1], sum[i-1][j]) + tri[i][j] 로
* 세우면 j를 1부터 시작해야 하는데, 그렇게 되면 0열의 값들이 누락되게 됨.
*/
for(int i=1; i<n; i++) {
for(int j=0; j<=i; j++) {
sum[i][j] = sum[i-1][j] + tri[i][j];
if(j > 0 && sum[i][j] < sum[i-1][j-1] + tri[i][j]) {
sum[i][j] = sum[i-1][j-1] + tri[i][j];
}
}
}
/* n-1행의 최댓값을 구함 */
int max = sum[n-1][0];
for(int j=0; j<n; j++) {
if(sum[n-1][j] > max) {
max = sum[n-1][j];
}
}
System.out.println(max);
}
}
알고리즘 문제 출처 : 백준 - 11055번 : 가장 큰 증가 부분 수열 https://www.acmicpc.net/problem/11055
내가 작성한 코드
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] a = new int[n]; //입력받을 배열
int[] sum = new int[n]; //sum[i] : a[i]가 가장 마지막에 오는 합
/* 입력받은 값을 배열에 할당 */
for(int i=0; i<n; i++) {
a[i] = sc.nextInt();
}
/* 배열 sum에 있는 값들은 모두 기본값인 0이다.
* 그러므로 sum[i]에 a[i]를 먼저 할당해준다.
* j번째 수는 i번째 수보다 앞에 있는 수인데
* a[i]가 a[j]보다 크고, sum[i]가 sum[j]+a[i]보다 작으면
* sum[i] = sum[j] + a[i]를 할당한다.
*
* 점화식은 sum[i] = max(sum[j] + a[i])
* a[i]가 가장 마지막에 오는 합(sum[i])은
* (i번째보다 앞에 있는 j번째의 값 a[j]가 마지막으로 오는 합) 중에서 가장 큰 값에 a[i]를 더한 값과 같다. */
for(int i=0; i<n; i++) {
sum[i] = a[i];
for(int j=0; j<i; j++) {
if(a[i] > a[j] && sum[i] < sum[j] + a[i]) {
sum[i] = sum[j] + a[i];
}
}
}
/* sum[i](a[i]가 가장 마지막에 오는 합) 중에서 가장 큰 값을 고른다. */
int max = sum[0];
for(int i=0; i<n; i++) {
if(max < sum[i]) {
max = sum[i];
}
}
System.out.println(max);
}
}
알고리즘 문제 출처 : 백준 - 11722번 : 가장 긴 감소하는 부분 수열 https://www.acmicpc.net/problem/11722
내가 작성한 코드
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] a = new int[n]; //입력받을 배열
int[] count = new int[n]; //count[i] : a[i]가 가장 마지막에 올 때, 개수
for(int i=0; i<n; i++) {
a[i] = sc.nextInt();
}
for(int i=0; i<n; i++) {
count[i] = 1;
for(int j=0; j<i; j++) {
if(a[i] < a[j] && count[i] < count[j] + 1) {
count[i] = count[j] + 1;
}
}
}
int answer = count[0];
for(int i=1; i<n; i++) {
if(answer < count[i]) {
answer = count[i];
}
}
System.out.println(answer);
}
}
알고리즘 문제 출처 : 백준 - 11054번 : 가장 긴 바이토닉 부분 수열 https://www.acmicpc.net/problem/11054
내가 작성한 코드
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] input = new int[n]; //입력받을 배열
int[] ascend = new int[n]; //ascend[i] : i번째 값으로 끝나는 증가하는 수열
int[] descend = new int[n]; //descend[i] : i번째 값으로 시작하는 감소하는 수열
/* 값 입력 */
for(int i=0; i<n; i++) {
input[i] = sc.nextInt();
}
/* i번째 값으로 끝나는 증가하는 수열 */
for(int i=0; i<n; i++) {
ascend[i] = 1;
for(int j=0; j<i; j++) {
if(input[i] > input[j] && ascend[i] < ascend[j] + 1) {
ascend[i] = ascend[j] + 1;
}
}
}
/* i번째 값으로 시작하는 감소하는 수열 */
for(int i=n-1; i>=0; i--) {
descend[i] = 1;
for(int j=i+1; j<n; j++) {
if(input[i] > input[j] && descend[i] < descend[j] + 1) {
descend[i] = descend[j] + 1;
}
}
}
/* 최대개수 구하기 */
int answer = ascend[0] + descend[0] -1; //input[0]이 중복으로 2번 들어갔으므로 1을 빼준다.
for(int i=1; i<n; i++) {
if(answer < ascend[i] + descend[i] - 1) {
answer = ascend[i] + descend[i] - 1;
}
}
System.out.println(answer);
}
}
알고리즘 문제 출처 : 백준 - 13398번 : 연속합 2 https://www.acmicpc.net/problem/13398
import java.util.Scanner;
public class Main {
//10 -4 3 1 5 6 -35 12 21 -1
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] input = new int[n]; //입력받을 배열
int[] front = new int[n]; //front[i] : 제거할 k번째 앞에 올, i번째까지의 합
int[] back = new int[n]; //back[i] : 제거할 k번째 뒤에 올, i번부터의 합
/* 값 입력 */
for(int i=0; i<n; i++) {
input[i] = sc.nextInt();
}
/* k번째 앞에 올 수 */
for(int i=0; i<n; i++) {
front[i] = input[i];
if(i>0 && front[i] < front[i-1] + input[i]) {
front[i] = front[i-1] + input[i];
}
}
/* k번째 뒤에 올 수 */
for(int i=n-1; i>=0; i--) {
back[i] = input[i];
if(i < n-1 && back[i] < back[i+1] + input[i]) {
back[i] = back[i+1] + input[i];
}
}
int max = front[0];
/* k번째 수를 빼지 않고 진행할 경우 */
for(int i=0; i<n; i++) {
if(max < front[i]) {
max = front[i];
}
}
/* k번째 수를 뺄 경우 */
for(int i=0; i<n; i++) {
if(i-1>=0 && i+1<n && max < front[i-1] + back[i+1]) {
max = front[i-1] + back[i+1];
}
}
System.out.println(max);
}
}
알고리즘 문제 출처 : 17404번 : RGB거리 2 https://www.acmicpc.net/problem/17404
내가 작성한 코드
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[][] cost = new int[n+1][3];
int[][] check = new int[n+1][3];
int max = 1000 * 1000 + 1;
/* 입력값을 cost 배열에 할당 */
for(int i=1; i<=n; i++) {
for(int j=0; j<3; j++) {
cost[i][j] = sc.nextInt();
}
}
for(int j=0; j<3; j++) {
/* j가 있는 for문을 돌 때마다 1번집의 색깔이 cost[1][j]로 결정됨 */
for(int i=0; i<3; i++) {
if(i==j) {
check[1][i] = cost[1][j];
}else {
check[1][i] = max;
}
}
/* check[i][0] i번째 집의 색깔이 R일 때의 최소합 */
for(int i=2; i<=n; i++) {
check[i][0] = Math.min(check[i-1][1], check[i-1][2]) + cost[i][0];
check[i][1] = Math.min(check[i-1][0], check[i-1][2]) + cost[i][1];
check[i][2] = Math.min(check[i-1][1], check[i-1][0]) + cost[i][2];
}
/* 위에서 결정된 1번집의 색깔과 n번집의 색깔을 다르게 해서 최소합 비교 */
for(int i=0; i<3; i++) {
if(i==j) continue;
if(max > check[n][i]) {
max = check[n][i];
}
}
}
System.out.println(max);
}
}