꾸물꾸물 졔의 개발공부
백준 2156 - 포도주 시식 ( JAVA ) 본문
시간초과 - 부분집합
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
import java.io.*;
import java.util.*;
public class Main_시간초과 {
public static int[] drink; //포도주 마셨으면 1
private static int n;
private static ArrayList<Integer> grape;
private static int max; // 최댓값
public static void main(String[] args) throws Exception{
BufferedReader br= new BufferedReader(new InputStreamReader(System.in));
n = Integer.parseInt(br.readLine()) ; // 포도주 잔의 갯수
drink = new int[n];
grape= new ArrayList<Integer>();
for(int i=0; i<n; i++) {
grape.add(Integer.parseInt(br.readLine()));
}
// 6 10 13 9 8 1
max=0;
// grape 리스트 원소 차례대로 시작해서 더해보기
for(int i=0; i<n; i++) {
getMax(i, 0);
}
System.out.println(max);
}// end of main
private static void getMax(int from, int link) { // from:마실 포도주 , link:연속으로 마신 포도주 갯수
if(link==2) {
from+=1;
link=0;
}
if(from >= n) {
int count=0;
for(int i=0; i<n; i++) {
if(drink[i] ==1 ) {
count += grape.get(i);
}
}
if(max < count) max = count;
return ;
}//이번꺼 먹을거면 ,
drink[from] = 1;
getMax(from+1, link+1);
//안먹을거면
drink[from]= 0;
getMax(from+1, 0);
}
}// end of class
|
cs |
→ 가능한 모든 경우의 수를 구했다 .
부분집합으로 구했고, 3개 연속으로 되지 않게 하기 위해 link 변수를 사용해 link 가 2가 되면 해당 포도주는 아예 먹지 못하도록 처리하였다 .
먹은 포도주는 drink 배열의 값을 1로 해서, 마지막에 값이 1인 포도주의 값을 더해주었다.
예제 답은 잘 나왔지만 시간초과가 났다 !!
런타임에러 - dp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
import java.io.*;
import java.util.*;
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()) ; // 포도주 잔의 갯수
int[] grape= new int[n]; //포도주 양
int[] dp = new int[n]; //각 위치까지의 포도주 최댓값 저장
for(int i=0; i<n; i++) {
grape[i] = Integer.parseInt(br.readLine());
}
// [0] [1] [2] [3] [4] [5]
// 6 10 13 9 8 1
// 두잔까지는 다 먹는게 최댓값
dp[0] = grape[0];
dp[1] = grape[0]+grape[1];
//세잔째에는, xoo 에서 dp[n-3] 인덱스가 음수됨 -> 따로 정의해주기
// oox oxo xoo
dp[2] = Math.max(dp[1], Math.max(dp[0]+grape[2], grape[1]+grape[2]));
for(int i=3; i<n; i++) {
// oox oxo xoo
dp[i] = Math.max(dp[i-1], Math.max(dp[i-2]+grape[i], dp[i-3]+grape[i-1]+grape[i]));
}
System.out.println(dp[n-1]);
}// end of main
}// end of class
|
cs |
→ dp 를 이용해서 풀었다.
각 지점까지의 최댓값을 구해서 dp 배열에 저장
1잔, 2잔까지는 포도주를 모두 마시는 것이 최댓값이기 때문에 dp[0] 과 dp[1] 은 따로 구해주었고,
이후부터는 3잔연속 안마시고, 최대한 많이 마시는 것을 찾아야한다.
이번에 마실 포도주가 i 번째 라고 할 때,
- oox ( 이전까지는 모두 마시고, 이번에는 안마심 ) = dp[i-1]
- oxo ( 이이전(?) 에는 마셨고, 바로 이전에는 안마셨고, 이번에 마심 ) = dp[i-2] + grape[i]
- xoo ( 이이전에는 안마셨고, 바로 이전에 마셨고, 이번에도 마심 ) = grape[i-3] + grape[i-1] + grape[i]
근데 !! 런타임에러가 발생했다.
포도주는 1개 이상이 주어진다. 만약 포도주가 하나만 있을 때, dp[1] 이후부터는 존재할 수가 없다.
그렇기 때문에 런타임 에러 발생 .
최종코드 - dp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
import java.io.*;
import java.util.*;
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()) ; // 포도주 잔의 갯수
int[] grape= new int[n]; //포도주 양
int[] dp = new int[n]; //각 위치까지의 포도주 최댓값 저장
for(int i=0; i<n; i++) {
grape[i] = Integer.parseInt(br.readLine());
}
// [0] [1] [2] [3] [4] [5]
// 6 10 13 9 8 1
// 한잔은 무조건 먹는게 최댓값
dp[0] = grape[0];
for(int i=1; i<n; i++) {
if(i==1) {
dp[1] = grape[0]+grape[1];
continue ; // 밑에 코드 안가게
}
if(i==2) {
dp[2] = Math.max(dp[1], Math.max(dp[0]+grape[2], grape[1]+grape[2]));
continue ;
}
// oox oxo xoo
dp[i] = Math.max(dp[i-1], Math.max(dp[i-2]+grape[i], dp[i-3]+grape[i-1]+grape[i]));
}
System.out.println(dp[n-1]);
}// end of main
}// end of class
|
cs |
→ 위의 런타임 에러를 방지 하기위해, 1잔 일때의 dp[0] 만 정의를 해두었다. (무조건 발생 )
이후부터는 반복문을 돌면서 , dp[1] 과, dp[2] 는 따로 조건을 걸어주었다.
- dp[1] = 두잔 : 무조건 두잔 다 마셔야 최댓값
- dp[2] = 세잔 : 3잔일 때는, xoo 에서 dp[i-3] 이 dp[-1] 로 존재 할 수 없기 때문에, grape[1] + grape[2] 로 따로 정의
- dp[3] ~ = oox /oxo / xoo 중 최댓값 구하기
※ i 가 1 일때와 2일 때는 if 문안의 코드만 실행 해야 하기때문에, continue 를 추가 해주었다.
'알고리즘 > 백준' 카테고리의 다른 글
백준 1946 - 신입 사원 (JAVA) (0) | 2022.08.24 |
---|---|
백준 16194 - 카드 구매하기 2 (JAVA) (0) | 2022.08.23 |
백준 9466 - 텀 프로젝트 (JAVA) (0) | 2022.08.19 |
백준 6603 - 로또 (JAVA) (0) | 2022.07.05 |
백준 11729 - 하노이 탑 이동 순서 (JAVA) (0) | 2022.06.25 |