잡동사니
[백준][java] 카드 구매하기11052
h-yujin
2022. 10. 2. 17:26
처음 시도한 방법
public class 카드구매하기11052 {
static int pay = 0;
static int max = 0;
public static void main(String[] args) throws NumberFormatException, IOException {
BufferedReader br =new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
StringTokenizer st = new StringTokenizer(br.readLine());
int[] arr = new int[n];
for(int i = 0; i<n; i++) {
arr[i] = Integer.parseInt(st.nextToken());
}
result(n, arr);
System.out.println(max);
}
private static void result(int n, int[] arr) {
if(n==0) {
if(max<pay) {
max=pay;
pay = 0;
}else {
pay = 0;
}
}else {
for(int i = 0 ;i<arr.length; i++) {
if(n-(i+1)>=0) {
n = n-(i+1);
pay += arr[i];
result(n, arr);
n = n+(i+1);
}else {
break;
}
}
}
}
}
트리 구조로 구현하였으나 시간초과로 실패했다.
하지만 보다시피 이렇게 구현하면 1+2와 2+1이 중복되는 것을 알 수 있다.
구글링을 통해 다른 방법을 찾았다.
일반항 구하기
public class 카드구매하기11052_2 {
public static void main(String[] args) throws NumberFormatException, IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
StringTokenizer st = new StringTokenizer(br.readLine());
int[] arr = new int[n + 1];
int[] d = new int[n + 1];
for (int i = 1; i <= n; i++) {
arr[i] = Integer.parseInt(st.nextToken());
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <=i; j++) {
d[i] = Math.max(d[i], d[i - j] + arr[j]);
}
}
System.out.println(d[n]);
}
}
- n이 3일 경우
- i 가 1일 경우
- d[1] 은 d[1]과 d[0]+arr[1]중 큰 숫자가 된다.
- d[1] = 0이고, d[0]+arr[1]은 0보다 크므로 후자가 된다.
- i가 2일 경우
- d[2]와
- d[1]+arr[1] → 카드를 1개 뽑을 경우 최대값과 카드가 1개 들어있는 팩 하나
- d[0]+arr[2] → 카드가 2개 들어있는 팩 하나
- 위의 두 가지 경우의 수를 비교하여 큰 값이 저장된다.
- d[2]와
- i가 3일 경우
- d[3]과
- d[2]+arr[1] → 카드가 2개 뽑을 경우 최대값과 카드가 1개 들어있는 팩 하나
- d[1]+arr[2] → 카드를 1개 뽑을 경우 최대값과 카드가 2개 들어있는 팩 하나
- d[0]+arr[3] → 카드가 3개 들어있는 팩 하나
- d[3]과
- i 가 1일 경우
- 이 알고리즘이 내가 처음 시도한 알고리즘과 다른 것은
- 배열 d에 카드를 1개 부터 n개 뽑을 경우 최대로 지불할 값을 저장해 둔다는 것이다.
- 따라서 모든 경우의 수를 배열d에 미리 저장된 값으로 간편하게 비교할 수 있다.
n=1 | d[1] |
n=2 | Math.max(d[2],…) |
n=3 | Math.max(d[3],…) |