일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 막내의막무가내 목표 및 회고
- 주택가 잠실새내
- 막내의막무가내 rxjava
- 막내의막무가내 SQL
- 막내의 막무가내
- 막내의 막무가내 알고리즘
- 막내의막무가내 프로그래밍
- 안드로이드 Sunflower 스터디
- 막내의막무가내
- 부스트코스
- 막내의막무가내 안드로이드 에러 해결
- 안드로이드
- 안드로이드 sunflower
- 막내의막무가내 코볼 COBOL
- flutter network call
- 프로그래머스 알고리즘
- 프래그먼트
- 주엽역 생활맥주
- 막내의막무가내 알고리즘
- Fragment
- 막무가내
- 막내의막무가내 안드로이드
- 막내의막무가내 코틀린
- 막내의막무가내 플러터 flutter
- 2022년 6월 일상
- 막내의막무가내 안드로이드 코틀린
- 부스트코스에이스
- 막내의막무가내 일상
- 막내의막무가내 플러터
- 막내의막무가내 코틀린 안드로이드
- Today
- Total
막내의 막무가내 프로그래밍 & 일상
[알고리즘] 백준 2565 전깃줄 -dp- 본문
https://www.acmicpc.net/problem/2565
2565번: 전깃줄
첫째 줄에는 두 전봇대 사이의 전깃줄의 개수가 주어진다. 전깃줄의 개수는 100 이하의 자연수이다. 둘째 줄부터 한 줄에 하나씩 전깃줄이 A전봇대와 연결되는 위치의 번호와 B전봇대와 연결되는 위치의 번호가 차례로 주어진다. 위치의 번호는 500 이하의 자연수이고, 같은 위치에 두 개 이상의 전깃줄이 연결될 수 없다.
www.acmicpc.net
이어 단계별 dp 문제를 풀어봤습니다. LIS 라는 것을 안보고 그냥 풀었었는데 LIS 개념은 다음 사이트나 구글링을 통해 볼 수 있습니다. Longest Increasing Subsequence, 최장증가부분수열 입니다.
최적화된 LIS(Longest Increasing Subsequence) 알고리즘과 해 찾기
LIS는 알고리즘 문제로써도, 코드 구현으로써도 너무나도 유명한 문제이지만 최적화된 해법을 찾는 과정은 문제 해결능력에 있어 큰 도움을 준다. 개인적으로 매력있게 느끼는점은 인간이 직관적으로 쉽게 찾을 수..
jins-dev.tistory.com
전깃줄 합선이 안되게 최소로 제거해야할 전깃줄을 구하는 문제였습니다. 역발상으로 전깃줄 제거가 아닌 최대 설치개수를 dp, LIS 로 구하고 최대 개수에서 뺴면 간단해지는 문제였습니다.
A전깃줄로 먼저 오름차순 정렬을 하여(그럼 반복문 돌며 B만 값 비교하여 신경쓰면 됨) 최대로 합선안되게 설치할 수 있는 전깃줄의 개수를 구하고 전체 개수에서 뺌으로써 최소제거 개수 결과를 도출할 수 있었습니다.
설명은 주석에 적어놨습니다.
풀이는 다음과 같습니다.
import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[][] num = new int[n + 1][2]; //[][1] : A 전깃줄 번호, [][2] : B 전깃줄 번호
int[] dp = new int[n + 1]; // 해당 위치까지의 가장 많이 설치할 수 있는 전깃줄 개수
int maxInstall = 1; //가장 많이 설치할 수 있는 개수
for (int i = 1; i <= n; i++) {
num[i][0] = sc.nextInt();
num[i][1] = sc.nextInt();
}
//[][0] 정렬 (A 전봇대 기준으로)
Arrays.sort(num, new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
return o1[0] - o2[0];
}
});
for (int i = 1; i <= n; i++) {
dp[i] = 1;
for (int j = 1; j < i; j++) {
if (num[j][1] < num[i][1]) { // 과거 A의 전깃줄과 이어진 B 번호보다 현재 B 번호가 더 커야 이을 수 있다.(A보다큰)
dp[i] = Math.max(dp[i], dp[j] + 1); // 과거 최대 전깃줄 개수 + 1 세팅
}
}
maxInstall = Math.max(maxInstall, dp[i]); // 최대 전깃줄 개수 세팅
}
System.out.println(n - maxInstall); //없애야 하는 전깃줄의 최소 개수 = 전체개수 - 가장많이설치할 수 있는 개수
}
}
추가로 저는 원래 for 반복문에서 이전에 풀었던 비슷한 dp 문제들 처럼
for (int i = 1; i <= n; i++) {
int max = 0;
for (int j = 1; j < i; j++) {
if (max < dp[j] && num[j][1] < num[i][1]) { // 과거 A의 전깃줄과 이어진 B 번호보다 현재 B 번호가 더 커야 이을 수 있다.(A보다큰)
max = dp[j];
}
}
dp[i] = max + 1;
maxInstall = Math.max(maxInstall, dp[i]); // 최대 전깃줄 개수 세팅
}
이런식으로 풀었었습니다. 그러나 밑 블로그 분의 풀이를 참고하고 이분의 코드가 더 깔끔하고 정석인 것 같아 코드를 바꾸고 앞으로도 비슷한 문제가 나오면 이렇게 풀려고 합니다.
https://hooongs.tistory.com/archive/20200111
2020/01/11 글 목록
hooongs.tistory.com
댓글과 공감은 큰 힘이 됩니다.