안녕하세요.
오늘의 문제는 7579번 앱입니다.
https://www.acmicpc.net/problem/7579
7579번: 앱
입력은 3줄로 이루어져 있다. 첫 줄에는 정수 N과 M이 공백문자로 구분되어 주어지며, 둘째 줄과 셋째 줄에는 각각 N개의 정수가 공백문자로 구분되어 주어진다. 둘째 줄의 N개의 정수는 현재 활
www.acmicpc.net
사실 더 빨리 포스팅을 했어야 했는데, 주말에는 이리저리 바빠서 월요일에 올리게 됐습니다. 백수라도 주말을 챙기고 싶은 이 심보는 무엇일까요
아무튼 시작하겠습니다.
<나의 풀이>
처음에는 굉장히 헤맸습니다.
이런 저런 방법을 생각하다 보니 , 떠오르는 문제가 있었습니다.
바로 첫 포스팅인 평범한 배낭 문제였습니다( https://hardworking-sloth.tistory.com/2 )
12865 평범한 배낭
드디어 블로그를 만들고 첫 글을 작성하네요. 23년에는 부지런하게 살겠다고 마음을 먹었지만, 23년 2월부터는 부지런히 살아야겠다로 다시 마음을 먹어야겠습니다. 화이팅.. 백준 12865 - 평범한
hardworking-sloth.tistory.com
이 문제도 최소(혹은 최대)의 상황을 구해야 하는 문제로 모든 경우를 다 확인해줘야 하는 문제입니다.
어떻게 효율적으로 확인할까 가 문제의 해결포인트입니다.
저는 평범한 배낭의 경험을 살려 메모지에이션을 사용하기로 했습니다. 물론 경험을 되살리는 것도 쉽지 않았습니다.
무엇을 저장할 것인지 생각하기 쉽지 않았지만 조건을 보고 확신했습니다.
조건 중 앱 비활성 비용(단위 초)이 0~100이고 N 또한 1~100이라 배열로 충분히 만들 수 있다고 생각했습니다.
memo [i][j] = x
i = i 번째 이하의 물건을 사용한다
j = j초가 주어졌때
x = 사용가능한 메모리
그리고 역시나 점화식을 세워보았습니다.
memo [i][j] = Math.max(memo [i-1][j] , memo [i-1][j-times [i]] + memorys [i] )
times [i] = i번째 앱의 비활성 시간
memory [i] = i번째 앱의 메모리
마지막으로 디테일한 조건 (degenerate?)만 좀 생각해 보았습니다.
1) memo [0]을 미리 채워줘야 한다.
2) M(문제에서 필요한 메모리)를 만족할 때마다 갱신해줘야 한다.
3) j(현재 주어진 초)가 time [i] 보다 클 때 점화식을 사용해야 한다.
<코드>
import java.io.*;
import java.util.StringTokenizer;
public class Num7579 {
static int[] memory, times;
static int answer,m,n;
static StringTokenizer st;
public static void main(String[] args) throws IOException {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
makeToken(bf.readLine());
n = Integer.parseInt(st.nextToken());
memory = new int[n];
times = new int[n];
m = Integer.parseInt(st.nextToken());
makeToken(bf.readLine());
for(int i=0;i<n;i++){
memory[i] = Integer.parseInt(st.nextToken());
}
makeToken(bf.readLine());
for(int i=0;i<n; i++){
times[i] = Integer.parseInt(st.nextToken());
}
answer = Integer.MAX_VALUE;
dp();
System.out.println(answer);
}
//이런거 메소드 만들어보기
public static void makeToken(String input){
st = new StringTokenizer(input," ");
}
public static void dp() {
int[][] memo = new int[n][10001];
for(int i=0;i<10001;i++){
if(i>=times[0]){
memo[0][i] = memory[0];
}
// 1번째 물건도 비교가 필요
if(m<=memo[0][i]){
answer = Math.min(i,answer);
}
}
for(int i=1;i<n;i++){
for(int j=0;j<10001;j++){
memo[i][j] = memo[i-1][j];
if(j>=times[i]){
memo[i][j] = Math.max(memo[i][j], memo[i-1][j- times[i]]+ memory[i]);
}
if(m<=memo[i][j]){
answer = Math.min(j,answer);
}
}
}
}
}
<후기>
1. 문제가 안 풀릴 때, 문제의 출처를 보지 말자 보통 초중고 문제라 속상해짐 ㅜ
2. 꼼꼼하게 생각하기 ( ex memo 배열을 10001이 아닌 5050으로 했음 갑자기 분위기 가우스 )
3. 맞춤법 검사 꼭 하자
'머리깨지며 배우는 코테풀이 > 백준 문제집 [단기간 성장]' 카테고리의 다른 글
[JAVA] 1039 교환 (0) | 2023.10.25 |
---|---|
[JAVA] 10942 팰린드롬? (0) | 2023.05.26 |
[JAVA] 4991 로봇청소기 (0) | 2023.05.17 |
[JAVA] 11049 행렬 곱셈 순서 (0) | 2023.04.19 |
[JAVA] 11066 파일 합치기 (0) | 2023.04.17 |