├── 그래프 ├── P1043_거짓말.java ├── P11403_경로찾기.java ├── P11404_플로이드.java ├── P11657_타임머신.java ├── P1197_최소신장트리.java ├── P1219_세일즈맨의고민.java ├── P1325_효율적인해킹.java ├── P1389_케빈베이컨의6단계법칙.java ├── P1414_불우이웃돕기.java ├── P1516_게임개발.java ├── P1707_이분그래프.java ├── P1717_집합표현하기.java ├── P17472_다리만들기.java ├── P1753_최단경로.java ├── P18352_특정거리도시찾기.java ├── P1854_K번째최단경로찾기.java ├── P1916_최소비용구하기.java ├── P1948_임계경로.java ├── P1976_여행계획짜기.java ├── P2251_물통.java └── P2252_줄세우기.java ├── 그리디 ├── P11047_동전개수최솟값.java ├── P1541_잃어버린괄호.java ├── P1715_카드정렬하기.java ├── P1744_수묶기.java └── P1931_회의실배정.java ├── 기하 ├── P11758_CCW.java ├── P17387_선분교차.java ├── P2162_선분그룹.java └── P2166_다각형의넓이.java ├── 동적계획법 ├── P10844_계단수.java ├── P11049_행렬곱연산횟수의최솟값.java ├── P11726_타일채우기.java ├── P1328_빌딩.java ├── P13398_연속된정수의합.java ├── P14003_가장길게증가하는부분수열.java ├── P14501_퇴사.java ├── P1463_1로만들기.java ├── P1915_가장큰정사각형.java ├── P2098_외판원순회.java ├── P2098_외판원순회_시간초과해결버전.java ├── P2193_이친수.java ├── P2342_DDR.java ├── P2747_피보나치수_BottomUp.java ├── P2747_피보나치수_TopDown.java └── P9252_LCS.java ├── 자료구조 ├── P10986_나머지합.java ├── P11003_최솟값찾기.java ├── P11268_절댓값힙.java ├── P11659_구간합구하기.java ├── P11660_구간합구하기2.java ├── P11720_숫자의합.java ├── P1253_좋은수.java ├── P12891_DNA비밀번호.java ├── P1546_평균.java ├── P17298_오큰수.java ├── P1874_스택수열.java ├── P1940_주몽.java ├── P2018_연속된자연수의합.java └── P2164_카드.java ├── 정렬 ├── P10989_수정렬하기3.java ├── P11004_K번째수.java ├── P11004_K번째수_병합정렬버전.java ├── P11399_ATM.java ├── P1377_버블소트1.java ├── P1427_내림차순정렬.java ├── P1517_버블소트2.java ├── P2750_수정렬하기.java └── P2751_수정렬하기2.java ├── 정수론 ├── P1016_제곱이아닌수.java ├── P1033_칵테일.java ├── P11689_GCDNK1.java ├── P1456_거의소수.java ├── P1747_소수팰린드롬.java ├── P1850_최대공약수.java ├── P1929_소수구하기.java ├── P1934_최소공배수.java └── P21568_AxByC.java ├── 조합 ├── P1010_다리놓기.java ├── P11050_이항계수.java ├── P11051_이항계수2.java ├── P1256_사전.java ├── P13251_조약돌꺼내기.java ├── P1722_순열의순서.java ├── P1947_선물전달.java └── P2775_부녀회장이될테야.java ├── 탐색 ├── P1167_트리의지름.java ├── P11724_연결요소의개수.java ├── P1206_DFS와BFS.java ├── P1300_K번째수.java ├── P13023_친구관계파악하기.java ├── P1920_원하는정수찾기.java ├── P2023_신기한소수.java ├── P2178_미로탐색.java └── P2343_블루레이.java └── 트리 ├── P1068_리프노드.java ├── P10868_최솟값.java ├── P11437_LCA.java ├── P11438_LCA2.java ├── P11505_구간곱구하기.java ├── P11725_트리의부모찾기.java ├── P14425_문자열찾기.java ├── P1991_트리순회.java └── P2042_구간합구하기3.java /그래프/P1043_거짓말.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.Scanner; 3 | public class P1043_거짓말 { 4 | public static int[] parent; 5 | public static int[] trueP; 6 | public static ArrayList[] party; 7 | public static int result; 8 | public static void main(String[] args) { 9 | Scanner sc = new Scanner(System.in); 10 | int N = sc.nextInt(); 11 | int M = sc.nextInt(); 12 | int T = sc.nextInt(); 13 | result = 0; 14 | trueP = new int[T]; 15 | for (int i = 0; i < T; i++) { // 진실을 아는 사람 저장 16 | trueP[i] = sc.nextInt(); 17 | } 18 | party = new ArrayList[M]; 19 | for (int i = 0; i < M; i++) { // 파티 데이터 저장 20 | party[i] = new ArrayList(); 21 | int party_size = sc.nextInt(); 22 | for (int j = 0; j < party_size; j++) { 23 | party[i].add(sc.nextInt()); 24 | } 25 | } 26 | parent = new int[N + 1]; 27 | for (int i = 0; i <= N; i++) { // 대표 노드를 자기 자신으로 초기화 하기 28 | parent[i] = i; 29 | } 30 | for (int i = 0; i < M; i++) { // 각 파티에 참여한 사람들을 하나의 그룹으로 만들기 -> union 연산 31 | int firstPeople = party[i].get(0); 32 | for (int j = 1; j < party[i].size(); j++) { 33 | union(firstPeople, party[i].get(j)); 34 | } 35 | } 36 | for (int i = 0; i < M; i++) { // 각 파티에서 진실을 아는 사람과 같은 그룹에 있다면 과장 할 수 없음 37 | boolean isPossible = true; 38 | int cur = party[i].get(0); 39 | for (int j = 0; j < trueP.length; j++) { 40 | if (find(cur) == find(trueP[j])) { 41 | isPossible = false; 42 | break; 43 | } 44 | } 45 | if (isPossible) 46 | result++; 47 | } 48 | System.out.println(result); 49 | } 50 | public static void union(int a, int b) { // union 연산 : 바로 연결이 아닌 대표 노드끼리 연결하여 줌 51 | a = find(a); 52 | b = find(b); 53 | if (a != b) { 54 | parent[b] = a; 55 | } 56 | } 57 | public static int find(int a) { // find 연산 58 | if (a == parent[a]) 59 | return a; 60 | else 61 | return parent[a] = find(parent[a]); // 재귀함수의 형태로 구현 62 | } 63 | public static boolean checkSame(int a, int b) { // 두 원소가 같은 집합인지 확인 64 | a = find(a); 65 | b = find(b); 66 | if (a == b) { 67 | return true; 68 | } 69 | return false; 70 | } 71 | } -------------------------------------------------------------------------------- /그래프/P11403_경로찾기.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.util.StringTokenizer; 3 | public class P11403_경로찾기 { 4 | private static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 5 | private static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); 6 | static int N; 7 | static int distance[][]; 8 | public static void main(String[] args) throws IOException { 9 | N = Integer.parseInt(br.readLine()); 10 | distance = new int[N][N]; 11 | for (int i = 0; i < N; i++) { 12 | StringTokenizer st = new StringTokenizer(br.readLine()); 13 | for (int j = 0; j < N; j++) { 14 | int v = Integer.parseInt(st.nextToken()); 15 | distance[i][j] = v; 16 | } 17 | } 18 | for (int k = 0; k < N; k++) { // 변형된 플로이드 워셜 알고리즘 수행 19 | for (int i = 0; i < N; i++) { 20 | for (int j = 0; j < N; j++) { 21 | if (distance[i][k]==1 && distance[k][j]==1) distance[i][j]=1; 22 | } 23 | } 24 | } 25 | for (int i = 0; i < N; i++) { 26 | for (int j = 0; j < N; j++) { 27 | System.out.print(distance[i][j] + " "); 28 | } 29 | System.out.println(); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /그래프/P11404_플로이드.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.util.StringTokenizer; 3 | public class P11404_플로이드 { 4 | private static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 5 | private static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); 6 | static int N, M; 7 | static int distance[][]; 8 | public static void main(String[] args) throws IOException { 9 | N = Integer.parseInt(br.readLine()); 10 | M = Integer.parseInt(br.readLine()); 11 | distance = new int[N + 1][N + 1]; 12 | for (int i = 1; i <= N; i++) { // 인접 행렬 초기화 13 | for (int j = 1; j <= N; j++) { 14 | if (i == j) 15 | distance[i][j] = 0; 16 | else 17 | distance[i][j] = 10000001; // 충분히 큰수로 저장 18 | } 19 | } 20 | for (int i = 0; i < M; i++) { 21 | StringTokenizer st = new StringTokenizer(br.readLine()); 22 | int s = Integer.parseInt(st.nextToken()); 23 | int e = Integer.parseInt(st.nextToken()); 24 | int v = Integer.parseInt(st.nextToken()); 25 | if (distance[s][e] > v) distance[s][e] = v; 26 | } 27 | for (int k = 1; k <= N; k++) { // 플로이드 워셜 알고리즘 수행 28 | for (int i = 1; i <= N; i++) { 29 | for (int j = 1; j <= N; j++) { 30 | if (distance[i][j] > distance[i][k] + distance[k][j]) 31 | distance[i][j] = distance[i][k] + distance[k][j]; 32 | } 33 | } 34 | } 35 | for (int i = 1; i <= N; i++) { 36 | for (int j = 1; j <= N; j++) { 37 | if (distance[i][j] == 10000001) System.out.print("0 "); 38 | else System.out.print(distance[i][j] + " "); 39 | } 40 | System.out.println(); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /그래프/P11657_타임머신.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.util.Arrays; 3 | import java.util.StringTokenizer; 4 | public class P11657_타임머신 { 5 | private static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 6 | private static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); 7 | static int N, M; 8 | static long distance[]; 9 | static Edge edges[]; 10 | public static void main(String[] args) throws IOException { 11 | StringTokenizer st = new StringTokenizer(br.readLine()); 12 | N = Integer.parseInt(st.nextToken()); 13 | M = Integer.parseInt(st.nextToken()); 14 | edges = new Edge[M + 1]; 15 | distance = new long[N + 1]; 16 | Arrays.fill(distance, Integer.MAX_VALUE); // 최단거리 배열 초기화 17 | for (int i = 0; i < M; i++) { // 간선 리스트에 데이터 저장하기 18 | st = new StringTokenizer(br.readLine()); 19 | int start = Integer.parseInt(st.nextToken()); 20 | int end = Integer.parseInt(st.nextToken()); 21 | int time = Integer.parseInt(st.nextToken()); 22 | edges[i] = new Edge(start, end, time); 23 | } 24 | // 벨만포드 알고리즘 수행 25 | distance[1] = 0; 26 | for (int i = 1; i < N; i++) { //N보다 하나 적은 수만큼 반복 27 | for (int j = 0; j < M; j++) { 28 | Edge edge = edges[j]; 29 | // 더 작은 최단거리 가 있는 경우 갱신 30 | if (distance[edge.start] != Integer.MAX_VALUE && distance[edge.end] > distance[edge.start] + edge.time) { 31 | distance[edge.end] = distance[edge.start] + edge.time; 32 | } 33 | } 34 | } 35 | boolean mCycle = false; 36 | for (int i = 0; i < M; i++) { // 음수 cycle 확인 37 | Edge edge = edges[i]; 38 | if (distance[edge.start] != Integer.MAX_VALUE && distance[edge.end] > distance[edge.start] + edge.time) { 39 | mCycle = true; 40 | } 41 | } 42 | if (!mCycle) { // 음의 cycle이 없는 경우 43 | for (int i = 2; i <= N; i++) { 44 | if (distance[i] == Integer.MAX_VALUE) 45 | System.out.println("-1"); 46 | else 47 | System.out.println(distance[i]); 48 | } 49 | } else { // 음의 cycle이 있는 경우 50 | System.out.println("-1"); 51 | } 52 | } 53 | } 54 | class Edge { // 간선리스트를 편하게 다루기 위해 클래스로 별도 구현 55 | int start, end, time; // 시작점, 도착점, 걸리는 시간 56 | public Edge(int start, int end, int time) { 57 | this.start = start; 58 | this.end = end; 59 | this.time = time; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /그래프/P1197_최소신장트리.java: -------------------------------------------------------------------------------- 1 | import java.util.PriorityQueue; 2 | import java.util.Scanner; 3 | 4 | public class P1197_최소신장트리 { 5 | static int[] parent; 6 | static PriorityQueue queue; 7 | public static void main(String[] args) { 8 | Scanner sc = new Scanner(System.in); 9 | int N = sc.nextInt(); // 노드의 수 10 | int M = sc.nextInt(); // 간선의 수 11 | queue = new PriorityQueue<>(); 12 | parent = new int[N + 1]; 13 | for (int i = 0; i < N; i++) { 14 | parent[i] = i; 15 | } 16 | for (int i = 0; i < M; i++) { 17 | int s = sc.nextInt(); 18 | int e = sc.nextInt(); 19 | int v = sc.nextInt(); 20 | queue.add(new pEdge(s, e, v)); 21 | } 22 | int useEdge = 0; 23 | int result = 0; 24 | while (useEdge < N - 1) { 25 | pEdge now = queue.poll(); 26 | if (find(now.s) != find(now.e)) // 같은 부모가 아니라면 -> 연결해도 싸이클이 생기지 않는다면 27 | { 28 | union(now.s, now.e); 29 | result = result + now.v; 30 | useEdge++; 31 | } 32 | } 33 | System.out.println(result); 34 | 35 | } 36 | public static void union(int a, int b) { // union 연산 : 대표 노드끼리 연결하여 줌 37 | a = find(a); 38 | b = find(b); 39 | if (a != b) { 40 | parent[b] = a; 41 | } 42 | } 43 | public static int find(int a) { // find 연산 44 | if (a == parent[a]) 45 | return a; 46 | else 47 | return parent[a] = find(parent[a]); // 재귀함수의 형태로 구현 -> 경로 압축 부분 48 | } 49 | } 50 | class pEdge implements Comparable { 51 | int s; 52 | int e; 53 | int v; 54 | pEdge(int s, int e, int v) { 55 | this.s = s; 56 | this.e = e; 57 | this.v = v; 58 | } 59 | @Override 60 | public int compareTo(pEdge o) { 61 | // TODO Auto-generated method stub 62 | return this.v - o.v; 63 | } 64 | } -------------------------------------------------------------------------------- /그래프/P1219_세일즈맨의고민.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.util.Arrays; 3 | import java.util.StringTokenizer; 4 | public class P1219_세일즈맨의고민 { 5 | private static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 6 | private static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); 7 | static int N, M, sCity, eCity; 8 | static long distance[],cityMoney[]; 9 | static Edge_1219 Edge_1219s[]; 10 | public static void main(String[] args) throws IOException { 11 | StringTokenizer st = new StringTokenizer(br.readLine()); 12 | N = Integer.parseInt(st.nextToken()); 13 | sCity = Integer.parseInt(st.nextToken()); 14 | eCity = Integer.parseInt(st.nextToken()); 15 | M = Integer.parseInt(st.nextToken()); 16 | Edge_1219s = new Edge_1219[M]; 17 | distance = new long[N]; 18 | cityMoney = new long[N]; 19 | Arrays.fill(distance, Long.MIN_VALUE); // 최단거리 배열 초기화 20 | for (int i = 0; i < M; i++) { // 간선 리스트에 데이터 저장하기 21 | st = new StringTokenizer(br.readLine()); 22 | int start = Integer.parseInt(st.nextToken()); 23 | int end = Integer.parseInt(st.nextToken()); 24 | int price = Integer.parseInt(st.nextToken()); 25 | Edge_1219s[i] = new Edge_1219(start, end, price); 26 | } 27 | st = new StringTokenizer(br.readLine()); 28 | for (int i = 0; i < N; i++) { 29 | cityMoney[i] = Long.parseLong(st.nextToken()); 30 | } 31 | distance[sCity] = cityMoney[sCity]; // 변형된 벨만포드 알고리즘 수행 32 | for (int i = 0; i <= N + 100; i++) { // 양수싸이클이 전파되도록 충분히 큰 수로 반복하기 33 | for (int j = 0; j < M; j++) { 34 | int start = Edge_1219s[j].start; 35 | int end = Edge_1219s[j].end; 36 | int price = Edge_1219s[j].price; 37 | if (distance[start] == Long.MIN_VALUE) continue; // 시작노드가 미방문 노드이면 skip 38 | // 시작 노드가 양수사이클에 연결된 노드라면 종료 노드도 연결 노드로 갱신 39 | else if (distance[start] == Long.MAX_VALUE) 40 | distance[end] = Long.MAX_VALUE; 41 | // 더 많은 돈을 벌수 있는 새로운 경로가 발견된 경우 새로운 경로 값으로 갱신 42 | else if (distance[end] < distance[start] + cityMoney[end] - price) { 43 | distance[end] = distance[start] + cityMoney[end] - price; 44 | // N-1 반복 이후 갱신되는 종료 노드는 양수사이클 연결 노드로 변경 45 | if (i >= N - 1) 46 | distance[end] = Long.MAX_VALUE; 47 | } 48 | } 49 | } 50 | if (distance[eCity] == Long.MIN_VALUE) System.out.println("gg"); // 도착 불가능 51 | else if (distance[eCity] == Long.MAX_VALUE) System.out.println("Gee"); // 양수사이클 연결 52 | else System.out.println(distance[eCity]); //그 이외의 경우 53 | } 54 | } 55 | class Edge_1219 { // 간선리스트를 편하게 다루기 위해 클래스로 별도 구현 56 | int start, end, price; // 시작점, 도착점, 걸리는 시간 57 | public Edge_1219(int start, int end, int price) { 58 | this.start = start; 59 | this.end = end; 60 | this.price = price; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /그래프/P1325_효율적인해킹.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedReader; 2 | import java.io.BufferedWriter; 3 | import java.io.IOException; 4 | import java.io.InputStreamReader; 5 | import java.io.OutputStreamWriter; 6 | import java.util.ArrayList; 7 | import java.util.LinkedList; 8 | import java.util.Queue; 9 | import java.util.StringTokenizer; 10 | public class P1325_효율적인해킹 { 11 | static int N, M; 12 | static boolean visited[]; 13 | static int answer[]; 14 | static ArrayList A[]; 15 | public static void main(String[] args) throws IOException { 16 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 17 | BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); 18 | StringTokenizer st = new StringTokenizer(br.readLine()); 19 | N = Integer.parseInt(st.nextToken()); 20 | M = Integer.parseInt(st.nextToken()); 21 | A = new ArrayList[N + 1]; 22 | answer = new int[N + 1]; 23 | for (int i = 1; i <= N; i++) 24 | A[i] = new ArrayList<>(); 25 | for (int i = 0; i < M; i++) { 26 | st = new StringTokenizer(br.readLine()); 27 | int S = Integer.parseInt(st.nextToken()); 28 | int E = Integer.parseInt(st.nextToken()); 29 | A[S].add(E); 30 | } 31 | for (int i = 1; i <= N; i++) { //모든 정점에 대하여 BFS 실행 32 | visited = new boolean[N + 1]; 33 | BFS(i); 34 | } 35 | int maxVal = 0; 36 | for (int i = 1; i <= N; i++) { 37 | maxVal = Math.max(maxVal, answer[i]); 38 | } 39 | for (int i = 1; i <= N; i++) { 40 | if (answer[i] == maxVal) //answer배열에서 maxVal와 같은 값을 가진 index를 정답으로 출력 41 | System.out.print(i + " "); 42 | } 43 | } 44 | public static void BFS(int index) { 45 | Queue queue = new LinkedList(); 46 | queue.add(index); 47 | visited[index] = true; 48 | while (!queue.isEmpty()) { 49 | int now_node = queue.poll(); 50 | for (int i : A[now_node]) { 51 | if (visited[i] == false) { 52 | visited[i] = true; 53 | answer[i]++; //신규 정점인덱스의 정답 배열 값을 증가 시키기 54 | queue.add(i); 55 | } 56 | } 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /그래프/P1389_케빈베이컨의6단계법칙.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.util.StringTokenizer; 3 | public class P1389_케빈베이컨의6단계법칙 { 4 | private static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 5 | private static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); 6 | static int N, M; 7 | static int distance[][]; 8 | public static void main(String[] args) throws IOException { 9 | StringTokenizer st = new StringTokenizer(br.readLine()); 10 | N = Integer.parseInt(st.nextToken()); 11 | M = Integer.parseInt(st.nextToken()); 12 | distance = new int[N + 1][N + 1]; 13 | for (int i = 1; i <= N; i++) { // 인접 행렬 초기화 14 | for (int j = 1; j <= N; j++) { 15 | if (i == j) 16 | distance[i][j] = 0; 17 | else 18 | distance[i][j] = 10000001; // 충분히 큰수로 저장 19 | } 20 | } 21 | for (int i = 0; i < M; i++) { // 친구 관계이므로 양방향 저장을 하며 1로 가중치 통일 22 | st = new StringTokenizer(br.readLine()); 23 | int s = Integer.parseInt(st.nextToken()); 24 | int e = Integer.parseInt(st.nextToken()); 25 | distance[s][e] = 1; 26 | distance[e][s] = 1; 27 | } 28 | for (int k = 1; k <= N; k++) { // 플로이드 워셜 알고리즘 수행 29 | for (int i = 1; i <= N; i++) { 30 | for (int j = 1; j <= N; j++) { 31 | if (distance[i][j] > distance[i][k] + distance[k][j]) 32 | distance[i][j] = distance[i][k] + distance[k][j]; 33 | } 34 | } 35 | } 36 | int Min = Integer.MAX_VALUE; 37 | int Answer = -1; 38 | for (int i = 1; i <= N; i++) { 39 | int temp = 0; 40 | for (int j = 1; j <= N; j++) { 41 | temp = temp + distance[i][j]; 42 | } 43 | if(Min>temp) // 가장 작은 케빈 베이컨의 수를 지니고 있는 i를 찾기 44 | { 45 | Min = temp; 46 | Answer = i; 47 | } 48 | } 49 | System.out.println(Answer); 50 | } 51 | } -------------------------------------------------------------------------------- /그래프/P1414_불우이웃돕기.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.util.*; 3 | public class P1414_불우이웃돕기 { 4 | static int[] parent; 5 | static int N, sum; 6 | static PriorityQueue queue; 7 | public static void main(String[] args) throws IOException { 8 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 9 | StringTokenizer st = new StringTokenizer(br.readLine()); 10 | N = Integer.parseInt(st.nextToken()); 11 | queue = new PriorityQueue<>(); 12 | for (int i = 0; i < N; i++) { 13 | st = new StringTokenizer(br.readLine()); 14 | char[] tempc = st.nextToken().toCharArray(); 15 | for (int j = 0; j < N; j++) { 16 | int temp = 0; 17 | if (tempc[j] >= 'a' && tempc[j] <= 'z') 18 | temp = tempc[j] - 'a' + 1; 19 | else if (tempc[j] >= 'A' && tempc[j] <= 'Z') 20 | temp = tempc[j] - 'A' + 27; 21 | sum = sum + temp; // 총 랜선의 길의 저장 22 | if (i != j && temp != 0)queue.add(new lEdge(i, j, temp)); 23 | } 24 | } 25 | parent = new int[N]; 26 | for (int i = 0; i < parent.length; i++)parent[i] = i; 27 | int useEdge = 0; 28 | int result = 0; 29 | while (!queue.isEmpty()) { // 최소 신장 트리 알고리즘을 수행하여 줍니다. 30 | lEdge now = queue.poll(); 31 | if (find(now.s) != find(now.e)){ // 같은 부모가 아니라면 -> 연결 가능 32 | union(now.s, now.e); 33 | result = result + now.v; 34 | useEdge++; 35 | } 36 | } 37 | if (useEdge == N - 1) System.out.println(sum - result); 38 | else System.out.println(-1); 39 | } 40 | public static void union(int a, int b) { // union 연산 : 대표 노드끼리 연결하여 줌 41 | a = find(a); b = find(b); 42 | if (a != b) parent[b] = a; 43 | } 44 | public static int find(int a) { // find 연산 45 | if (a == parent[a]) return a; 46 | else return parent[a] = find(parent[a]); // 재귀함수의 형태로 구현 -> 경로 압축 부분 47 | } 48 | } 49 | class lEdge implements Comparable { 50 | int s, e, v; 51 | lEdge(int s, int e, int v) { 52 | this.s = s; 53 | this.e = e; 54 | this.v = v; 55 | } 56 | @Override 57 | public int compareTo(lEdge o) { 58 | return this.v - o.v; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /그래프/P1516_게임개발.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedReader; 2 | import java.io.InputStreamReader; 3 | import java.util.ArrayList; 4 | import java.util.LinkedList; 5 | import java.util.Queue; 6 | import java.util.StringTokenizer; 7 | public class P1516_게임개발 { 8 | public static void main(String[] args) throws Exception { 9 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 10 | int N = Integer.parseInt(br.readLine()); 11 | ArrayList> A = new ArrayList<>(); 12 | for (int i = 0; i <= N; i++) { 13 | A.add(new ArrayList<>()); 14 | } 15 | int[] indegree = new int[N + 1]; // 진입차수배열 16 | int[] selfBuild = new int[N + 1]; // 자기자신을 짓는데 걸리는 시간 17 | for (int i = 1; i <= N; i++) { 18 | StringTokenizer st = new StringTokenizer(br.readLine()); 19 | selfBuild[i] = Integer.parseInt(st.nextToken()); // 해당 건물을 짓기 위한 시간 20 | while (true) { // 인접리스트 초기화 21 | int preTemp = Integer.parseInt(st.nextToken()); 22 | if (preTemp == -1) 23 | break; 24 | A.get(preTemp).add(i); 25 | indegree[i]++; // 진입차수 배열 초기화 26 | } 27 | } 28 | // 위상 정렬 29 | Queue queue = new LinkedList<>(); 30 | for (int i = 1; i <= N; i++) { 31 | if (indegree[i] == 0) { 32 | queue.offer(i); 33 | } 34 | } 35 | int[] result = new int[N + 1]; 36 | while (!queue.isEmpty()) { 37 | int now = queue.poll(); 38 | for (int next : A.get(now)) { 39 | indegree[next]--; 40 | result[next] = Math.max(result[next], result[now] + selfBuild[now]); 41 | if (indegree[next] == 0) { 42 | queue.offer(next); 43 | } 44 | } 45 | } 46 | for (int i = 1; i <= N; i++) { 47 | System.out.println(result[i] + selfBuild[i]); 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /그래프/P1707_이분그래프.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedReader; 2 | import java.io.InputStreamReader; 3 | import java.util.ArrayList; 4 | public class P1707_이분그래프 { 5 | static ArrayList[] A; 6 | static int[] check; 7 | static boolean visited[]; 8 | static boolean IsEven; 9 | public static void main(String[] args) throws Exception { 10 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 11 | int N = Integer.parseInt(br.readLine()); 12 | for (int t = 0; t < N; t++) { 13 | String[] s = br.readLine().split(" "); 14 | int V = Integer.parseInt(s[0]); 15 | int E = Integer.parseInt(s[1]); 16 | A = new ArrayList[V + 1]; 17 | visited = new boolean[V + 1]; 18 | check = new int[V + 1]; 19 | IsEven = true; 20 | for (int i = 1; i <= V; i++) { 21 | A[i] = new ArrayList(); 22 | } 23 | for (int i = 0; i < E; i++) { // 인접 리스트로 그래프 저장 24 | s = br.readLine().split(" "); 25 | int Start = Integer.parseInt(s[0]); 26 | int End = Integer.parseInt(s[1]); 27 | A[Start].add(End); 28 | A[End].add(Start); 29 | } 30 | for (int i = 1; i <= V; i++) { // 주어진 그래프가 하나로 연결되어 있다는 보장이 없으므로 모든 정점에서 수행 31 | if (IsEven) 32 | DFS(i); 33 | else 34 | break; 35 | } 36 | check[1] = 0; 37 | if (IsEven) 38 | System.out.println("YES"); 39 | else 40 | System.out.println("NO"); 41 | } 42 | } 43 | public static void DFS(int node) { // DFS구현 44 | visited[node] = true; 45 | for (int i : A[node]){ 46 | if (!visited[i]) { 47 | check[i] = (check[node] + 1) % 2; // 인접한 정점은 같은 집합이 아니므로 이전 정점과 다른 집합으로 처리 48 | DFS(i); 49 | } 50 | else if (check[node] == check[i]){ // 이미 방문한 정점이 현재 내 정점과 같은 집합이면 이분 그래프가 아님 51 | IsEven = false; 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /그래프/P1717_집합표현하기.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | public class P1717_집합표현하기 { 3 | public static int[] parent; 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | int N = sc.nextInt(); 7 | int M = sc.nextInt(); 8 | parent = new int[N + 1]; 9 | for (int i = 0; i <= N; i++) { // 대표 노드를 자기 자신으로 초기화 하기 10 | parent[i] = i; 11 | } 12 | for (int i = 0; i < M; i++) { 13 | int question = sc.nextInt(); 14 | int a = sc.nextInt(); 15 | int b = sc.nextInt(); 16 | if (question == 0) { // 집합합치기 17 | union(a, b); 18 | } else { // 같은 집합의 원소인지 확인하기 19 | if (checkSame(a, b)) { 20 | System.out.println("YES"); 21 | } else { 22 | System.out.println("NO"); 23 | } 24 | } 25 | } 26 | } 27 | public static void union(int a, int b) { // union 연산 : 바로 연결이 아닌 대표 노드끼리 연결하여 줌 28 | a = find(a); 29 | b = find(b); 30 | if (a != b) { 31 | parent[b] = a; 32 | } 33 | } 34 | public static int find(int a) { // find 연산 35 | if (a == parent[a]) 36 | return a; 37 | else 38 | return parent[a] = find(parent[a]); // 재귀함수의 형태로 구현 39 | } 40 | public static boolean checkSame(int a, int b) { // 두 원소가 같은 집합인지 확인 41 | a = find(a); 42 | b = find(b); 43 | if (a == b) { 44 | return true; 45 | } 46 | return false; 47 | } 48 | } -------------------------------------------------------------------------------- /그래프/P17472_다리만들기.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.util.*; 3 | public class P17472_다리만들기 { 4 | static int[] dr = { -1, 0, 1, 0 }; 5 | static int[] dc = { 0, 1, 0, -1 }; 6 | static int[] parent; 7 | static int[][] map; 8 | static int N, M, sNum; 9 | static boolean[][] visited; 10 | static ArrayList> sumlist; 11 | static ArrayList mlist; 12 | static PriorityQueue queue; 13 | public static void main(String[] args) throws IOException { 14 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 15 | StringTokenizer st = new StringTokenizer(br.readLine()); 16 | N = Integer.parseInt(st.nextToken()); // 가로크기 17 | M = Integer.parseInt(st.nextToken()); // 세로크기 18 | map = new int[N][M]; 19 | visited = new boolean[N][M]; 20 | for (int i = 0; i < N; i++) { 21 | st = new StringTokenizer(br.readLine()); 22 | for (int j = 0; j < M; j++) { 23 | map[i][j] = Integer.parseInt(st.nextToken()); //맵 정보 저장 24 | } 25 | } 26 | sNum = 1; 27 | sumlist = new ArrayList<>(); 28 | for (int i = 0; i < N; i++) { //각 자리에서 BFS 탐색을 이용하여 섬들을 분리하여 줍니다. 29 | for (int j = 0; j < M; j++) { 30 | if (map[i][j] != 0 && visited[i][j] != true) { 31 | BFS(i, j); 32 | sNum++; 33 | sumlist.add(mlist); 34 | } 35 | } 36 | } 37 | queue = new PriorityQueue<>(); 38 | for (int i = 0; i < sumlist.size(); i++) { //섬의 각 지점에서 만들수 있는 모든 간선을 저장 39 | ArrayList now = sumlist.get(i); 40 | for (int j = 0; j < now.size(); j++) { 41 | int r = now.get(j)[0]; 42 | int c = now.get(j)[1]; 43 | int now_S = map[r][c]; 44 | for (int d = 0; d < 4; d++) { //4방향 검색 45 | int tempR = dr[d]; 46 | int tempC = dc[d]; 47 | int blenght = 0; 48 | while (r + tempR >= 0 && r + tempR < N && c + tempC >= 0 && c + tempC < M) { 49 | if (map[r + tempR][c + tempC] == now_S) //같은 섬이면 간선을 만들수 없음 50 | break; 51 | else if (map[r + tempR][c + tempC] != 0) { //같은 섬이 아니고 바다가 아니면 52 | if (blenght > 1) // 다른 섬 -> 길이가 1이상일때 간선으로 더해줍니다. 53 | queue.add(new bEdge(now_S, map[r + tempR][c + tempC], blenght)); 54 | break; 55 | } else //바다이면 다리의 길이를 연장하여 줍니다. 56 | blenght++; 57 | if (tempR < 0)tempR--; 58 | else if (tempR > 0)tempR++; 59 | else if (tempC < 0)tempC--; 60 | else if (tempC > 0)tempC++; 61 | } 62 | } 63 | } 64 | } 65 | parent = new int[sNum]; 66 | for (int i = 0; i < parent.length; i++) { 67 | parent[i] = i; 68 | } 69 | int useEdge = 0; 70 | int result = 0; 71 | while (!queue.isEmpty()) { //최소 신장 트리 알고리즘을 수행하여 줍니다. 72 | bEdge now = queue.poll(); 73 | if (find(now.s) != find(now.e)) // 같은 부모가 아니라면 -> 연결 가능 74 | { 75 | union(now.s, now.e); 76 | result = result + now.v; 77 | useEdge++; 78 | } 79 | } 80 | if (useEdge == sNum - 2) { 81 | System.out.println(result); 82 | } else { 83 | System.out.println(-1); 84 | } 85 | } 86 | public static void union(int a, int b) { // union 연산 : 대표 노드끼리 연결하여 줌 87 | a = find(a); 88 | b = find(b); 89 | if (a != b) { 90 | parent[b] = a; 91 | } 92 | } 93 | public static int find(int a) { // find 연산 94 | if (a == parent[a]) 95 | return a; 96 | else 97 | return parent[a] = find(parent[a]); // 재귀함수의 형태로 구현 -> 경로 압축 부분 98 | } 99 | private static void BFS(int i, int j) { // BFS를 통하여 연결된 섬을 찾아줍니다. 100 | Queue queue = new LinkedList<>(); 101 | mlist = new ArrayList<>(); 102 | int[] start = { i, j }; 103 | queue.add(start); 104 | mlist.add(start); 105 | visited[i][j] = true; 106 | map[i][j] = sNum; 107 | while (!queue.isEmpty()) { 108 | int now[] = queue.poll(); 109 | int r = now[0]; 110 | int c = now[1]; 111 | for (int d = 0; d < 4; d++) { //4방향 검색 112 | int tempR = dr[d]; 113 | int tempC = dc[d]; 114 | while (r + tempR >= 0 && r + tempR < N && c + tempC >= 0 && c + tempC < M) { 115 | //현재 방문한 적이 없고 바다가 아니면 같은 섬으로 취급 116 | if (visited[r + tempR][c + tempC] == false && map[r + tempR][c + tempC] != 0) { 117 | addNode(r + tempR, c + tempC, queue); 118 | } else break; 119 | if (tempR < 0)tempR--; 120 | else if (tempR > 0)tempR++; 121 | else if (tempC < 0)tempC--; 122 | else if (tempC > 0)tempC++; 123 | } 124 | } 125 | } 126 | } 127 | //특정 위치를 섬 정보로 넣어주는 함수 128 | private static void addNode(int i, int j, Queue queue) { 129 | map[i][j] = sNum; 130 | visited[i][j] = true; 131 | int[] temp = { i, j }; 132 | mlist.add(temp); 133 | queue.add(temp); 134 | } 135 | } 136 | class bEdge implements Comparable { 137 | int s,e,v; 138 | bEdge(int s, int e, int v) { 139 | this.s = s; 140 | this.e = e; 141 | this.v = v; 142 | } 143 | @Override 144 | public int compareTo(bEdge o) { 145 | // TODO Auto-generated method stub 146 | return this.v - o.v; 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /그래프/P1753_최단경로.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | import java.io.*; 3 | public class P1753_최단경로 { 4 | public static int V,E,K; 5 | public static int distance[]; 6 | public static boolean visited[]; 7 | public static ArrayList list[]; 8 | public static PriorityQueue q = new PriorityQueue(); 9 | public static void main(String[] args) throws IOException { 10 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 11 | StringTokenizer st; 12 | st = new StringTokenizer(br.readLine()); 13 | V = Integer.parseInt(st.nextToken()); 14 | E = Integer.parseInt(st.nextToken()); 15 | K = Integer.parseInt(br.readLine()); 16 | distance = new int[V + 1]; 17 | visited = new boolean[V + 1]; 18 | list = new ArrayList[V + 1]; 19 | for (int i = 1; i <= V; i++) 20 | list[i] = new ArrayList(); 21 | for (int i = 0; i <= V; i++) { 22 | distance[i] = Integer.MAX_VALUE; 23 | } 24 | for (int i = 0; i < E; i++) { // 가중치가 있는 인접 리스트 초기화 25 | st = new StringTokenizer(br.readLine()); 26 | int u = Integer.parseInt(st.nextToken()); 27 | int v = Integer.parseInt(st.nextToken()); 28 | int w = Integer.parseInt(st.nextToken()); 29 | list[u].add(new Edge_1753(v, w)); 30 | } 31 | q.add(new Edge_1753(K, 0)); // K를 시작점으로 설정 32 | distance[K] = 0; 33 | while (!q.isEmpty()) { 34 | Edge_1753 current = q.poll(); 35 | int c_v = current.vertex; 36 | if (visited[c_v]) continue; // 기 방문 노드는 다시 큐에 넣지 않습니다. 37 | visited[c_v] = true; 38 | for (int i = 0; i < list[c_v].size(); i++) { 39 | Edge_1753 tmp = list[c_v].get(i); 40 | int next = tmp.vertex; 41 | int value = tmp.value; 42 | if (distance[next] > distance[c_v] + value) { // 최소 거리로 업데이트 43 | distance[next] = value + distance[c_v]; 44 | q.add(new Edge_1753(next, distance[next])); 45 | } 46 | }} 47 | for (int i = 1; i <= V; i++) { // 거리 배열 출력 48 | if (visited[i]) 49 | System.out.println(distance[i]); 50 | else 51 | System.out.println("INF"); 52 | }}} 53 | class Edge_1753 implements Comparable { 54 | int vertex, value; 55 | Edge_1753(int vertex, int value) { 56 | this.vertex = vertex; 57 | this.value = value; 58 | } 59 | public int compareTo(Edge_1753 e) { 60 | if (this.value > e.value) return 1; 61 | else return -1; 62 | }} -------------------------------------------------------------------------------- /그래프/P18352_특정거리도시찾기.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class P18352_특정거리도시찾기 { 3 | static int visited[]; 4 | static ArrayList[] A; 5 | static int N,M,K,X; 6 | static List answer; 7 | public static void main(String[] args) { 8 | Scanner scan = new Scanner(System.in); 9 | N = scan.nextInt(); // 정점의 수 10 | M = scan.nextInt(); // 간선의 수 11 | K = scan.nextInt(); // 간선의 수 12 | X = scan.nextInt(); // 간선의 수 13 | A = new ArrayList[N + 1]; 14 | answer = new ArrayList<>(); 15 | for (int i = 1; i <= N; i++) { 16 | A[i] = new ArrayList(); 17 | } 18 | for (int i = 0; i < M; i++) { 19 | int S = scan.nextInt(); 20 | int E = scan.nextInt(); 21 | A[S].add(E); 22 | } 23 | visited = new int[N + 1]; //방문 배열 초기화 24 | for(int i=0;i<=N;i++){ 25 | visited[i]=-1; 26 | } 27 | BFS(X); 28 | for(int i=0;i<=N;i++){ 29 | if(visited[i]==K) { 30 | answer.add(i); 31 | } 32 | } 33 | if(answer.isEmpty()){ 34 | System.out.println("-1"); 35 | } 36 | else{ 37 | Collections.sort(answer); 38 | for(int temp:answer){ 39 | System.out.println(temp); 40 | } 41 | } 42 | } 43 | // BFS구현 44 | private static void BFS(int node) { 45 | Queue queue = new LinkedList(); 46 | queue.add(node); 47 | visited[node]++; 48 | while (!queue.isEmpty()) { 49 | int now_node = queue.poll(); 50 | for (int i : A[now_node]) { 51 | if (visited[i]==-1) { 52 | visited[i] = visited[now_node]+1; 53 | queue.add(i); 54 | } 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /그래프/P1854_K번째최단경로찾기.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.util.Comparator; 3 | import java.util.PriorityQueue; 4 | import java.util.StringTokenizer; 5 | public class P1854_K번째최단경로찾기 { 6 | static final int INF = 100000000; 7 | public static void main(String[] args) throws IOException { 8 | int N, M, K; 9 | int[][] W = new int[1001][1001]; 10 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 11 | BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); 12 | StringTokenizer st = new StringTokenizer(br.readLine()); 13 | N = Integer.parseInt(st.nextToken()); 14 | M = Integer.parseInt(st.nextToken()); 15 | K = Integer.parseInt(st.nextToken()); 16 | PriorityQueue[] distQueue = new PriorityQueue[N + 1]; 17 | Comparator cp = new Comparator() { // 오름차순으로 정렬 기준 설정 18 | @Override 19 | public int compare(Integer o1, Integer o2) { 20 | return o1 < o2 ? 1 : -1; 21 | } 22 | }; 23 | for (int i = 0; i < N + 1; i++) { 24 | distQueue[i] = new PriorityQueue(K, cp); 25 | } 26 | for (int i = 0; i < M; i++) { // 인접행렬에 그래프 데이터 저장 27 | 28 | st = new StringTokenizer(br.readLine()); 29 | int a = Integer.parseInt(st.nextToken()); 30 | int b = Integer.parseInt(st.nextToken()); 31 | int c = Integer.parseInt(st.nextToken()); 32 | 33 | W[a][b] = c; 34 | } 35 | PriorityQueue pq = new PriorityQueue<>(); 36 | pq.add(new Node(1, 0)); 37 | distQueue[1].add(0); 38 | while (!pq.isEmpty()) { 39 | Node u = pq.poll(); 40 | for (int adjNode = 1; adjNode <= N; adjNode++) { 41 | // 연결된 모든 노드에 대하여 검색하기 (시간복잡토 측면에서 인접행렬이 불리한이유) 42 | if (W[u.node][adjNode] != 0) { 43 | // 저장된 경로가 K개가 안될 경우 그냥 추가한다. 44 | if (distQueue[adjNode].size() < K) { 45 | distQueue[adjNode].add(u.cost + W[u.node][adjNode]); 46 | pq.add(new Node(adjNode, u.cost + W[u.node][adjNode])); 47 | } 48 | // 저장된 경로가 K개이고, 현재 가장 큰 값보다 작을때만 추가한다. 49 | else if (distQueue[adjNode].peek() > u.cost + W[u.node][adjNode]) { 50 | distQueue[adjNode].poll(); // 기존 큐에서 Max값 삭제먼저 해주어야함 51 | distQueue[adjNode].add(u.cost + W[u.node][adjNode]); 52 | pq.add(new Node(adjNode, u.cost + W[u.node][adjNode])); 53 | } 54 | } 55 | } 56 | } 57 | for (int i = 1; i <= N; i++) { // K번째 경로 출력 58 | if (distQueue[i].size() == K) { 59 | bw.write(distQueue[i].peek() + "\n"); 60 | } else { 61 | bw.write(-1 + "\n"); 62 | } 63 | } 64 | bw.flush(); 65 | bw.close(); 66 | br.close(); 67 | } 68 | } 69 | //노드 클래스 작성 70 | class Node implements Comparable { 71 | int node; 72 | int cost; 73 | Node(int node, int cost) { 74 | this.node = node; 75 | this.cost = cost; 76 | } 77 | @Override 78 | public int compareTo(Node o) { 79 | return this.cost < o.cost ? -1 : 1; 80 | } 81 | } 82 | 83 | -------------------------------------------------------------------------------- /그래프/P1916_최소비용구하기.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedReader; 2 | import java.io.BufferedWriter; 3 | import java.io.InputStreamReader; 4 | import java.io.OutputStreamWriter; 5 | import java.util.ArrayList; 6 | import java.util.Arrays; 7 | import java.util.PriorityQueue; 8 | import java.util.StringTokenizer; 9 | public class P1916_최소비용구하기 { 10 | static int N, M; 11 | static ArrayList[] list; // 인접리스트로 그래프 표현하기. 12 | static int[] dist; // 최단거리 배열. 13 | static boolean[] visit; // 사용노드인지 확인하는 배열. 14 | public static void main(String[] args) throws Exception { 15 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 16 | BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); 17 | StringTokenizer st; 18 | N = Integer.parseInt(br.readLine()); 19 | M = Integer.parseInt(br.readLine()); 20 | list = new ArrayList[N + 1]; 21 | dist = new int[N + 1]; 22 | visit = new boolean[N + 1]; 23 | Arrays.fill(dist, Integer.MAX_VALUE); 24 | for (int i = 0; i <= N; i++) { 25 | list[i] = new ArrayList(); 26 | } 27 | for (int i = 0; i < M; i++) { // 주어진 그래프의 간선들을 인접리스트 자료구조에 넣는 부분 28 | st = new StringTokenizer(br.readLine()); 29 | int start = Integer.parseInt(st.nextToken()); 30 | int end = Integer.parseInt(st.nextToken()); 31 | int weight = Integer.parseInt(st.nextToken()); 32 | list[start].add(new Node_1916(end, weight)); 33 | } 34 | st = new StringTokenizer(br.readLine()); 35 | int startIndex = Integer.parseInt(st.nextToken()); 36 | int endIndex = Integer.parseInt(st.nextToken()); 37 | // 다익스트라 알고리즘 수행 38 | bw.write(dijkstra(startIndex, endIndex) + "\n"); 39 | bw.flush(); 40 | bw.close(); 41 | br.close(); 42 | } 43 | public static int dijkstra(int start, int end) { // 다익스트라 알고리즘 44 | PriorityQueue pq = new PriorityQueue<>(); 45 | pq.offer(new Node_1916(start, 0)); 46 | dist[start] = 0; 47 | while (!pq.isEmpty()) { 48 | Node_1916 nowNode_1916 = pq.poll(); 49 | int now = nowNode_1916.targetNode_1916; 50 | if (!visit[now]) { 51 | visit[now] = true; 52 | for (Node_1916 n : list[now]) { // 선택노드 + 비용 < 타켓노드인 경우 값을 갱신하는 부분 53 | if (!visit[n.targetNode_1916] && dist[n.targetNode_1916] > dist[now] + n.value) { 54 | dist[n.targetNode_1916] = dist[now] + n.value; 55 | pq.add(new Node_1916(n.targetNode_1916, dist[n.targetNode_1916])); 56 | } 57 | } 58 | } 59 | } 60 | return dist[end]; 61 | } 62 | } 63 | class Node_1916 implements Comparable { 64 | int targetNode_1916; 65 | int value; 66 | 67 | Node_1916(int targetNode_1916, int value) { 68 | this.targetNode_1916 = targetNode_1916; 69 | this.value = value; 70 | } 71 | @Override 72 | public int compareTo(Node_1916 o) { 73 | return value - o.value; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /그래프/P1948_임계경로.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedReader; 2 | import java.io.InputStreamReader; 3 | import java.util.ArrayList; 4 | import java.util.LinkedList; 5 | import java.util.Queue; 6 | import java.util.StringTokenizer; 7 | public class P1948_임계경로 { 8 | public static void main(String[] args) throws Exception { 9 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 10 | int N = Integer.parseInt(br.readLine()); 11 | int M = Integer.parseInt(br.readLine()); 12 | ArrayList> A = new ArrayList<>(); 13 | ArrayList> reverseA = new ArrayList<>(); 14 | for (int i = 0; i <= N; i++) { 15 | A.add(new ArrayList<>()); 16 | reverseA.add(new ArrayList<>()); 17 | } 18 | int[] indegree = new int[N + 1]; // 진입차수배열 19 | for (int i = 0; i < M; i++) { 20 | StringTokenizer st = new StringTokenizer(br.readLine()); 21 | int S = Integer.parseInt(st.nextToken()); 22 | int E = Integer.parseInt(st.nextToken()); 23 | int V = Integer.parseInt(st.nextToken()); 24 | A.get(S).add(new dNode(E, V)); 25 | reverseA.get(E).add(new dNode(S, V)); //역방향 간선 정보 저장 26 | indegree[E]++; // 진입차수 배열 초기화 27 | } 28 | StringTokenizer st = new StringTokenizer(br.readLine()); 29 | int startDosi = Integer.parseInt(st.nextToken()); 30 | int endDosi = Integer.parseInt(st.nextToken()); 31 | // 위상 정렬 32 | Queue queue = new LinkedList<>(); 33 | queue.offer(startDosi); 34 | int[] result = new int[N + 1]; 35 | while (!queue.isEmpty()) { 36 | int now = queue.poll(); 37 | for (dNode next : A.get(now)) { 38 | indegree[next.targetNode]--; 39 | result[next.targetNode] = Math.max(result[next.targetNode], result[now] + next.value); 40 | if (indegree[next.targetNode] == 0) { 41 | queue.offer(next.targetNode); 42 | } 43 | } 44 | } 45 | // 위상 정렬 reverse 46 | int resultCount = 0; 47 | boolean visited[] = new boolean[N + 1]; 48 | queue = new LinkedList<>(); 49 | queue.offer(endDosi); 50 | visited[endDosi] = true; 51 | while (!queue.isEmpty()) { 52 | int now = queue.poll(); 53 | for (dNode next : reverseA.get(now)) { 54 | if (result[next.targetNode] + next.value == result[now]) { //1분도 쉬지 않는 도로 체크 55 | resultCount++; 56 | if (visited[next.targetNode] == false) { //중복 카운트 방지를 위해 기 방문 노드 제외 57 | visited[next.targetNode] = true; 58 | queue.offer(next.targetNode); 59 | } 60 | } 61 | } 62 | } 63 | System.out.println(result[endDosi]); 64 | System.out.println(resultCount); 65 | } 66 | } 67 | class dNode { 68 | int targetNode; 69 | int value; 70 | dNode(int targetNode, int value) { 71 | this.targetNode = targetNode; 72 | this.value = value; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /그래프/P1976_여행계획짜기.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | public class P1976_여행계획짜기 { 3 | public static int[] parent; 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | int N = sc.nextInt(); 7 | int M = sc.nextInt(); 8 | int[][] dosi = new int[N + 1][N + 1]; 9 | for (int i = 1; i <= N; i++) { //도시 연결 데이터 저장 10 | for (int j = 1; j <= N; j++) { 11 | dosi[i][j] = sc.nextInt(); 12 | } 13 | } 14 | int[] route = new int[M + 1]; 15 | for (int i = 1; i <= M; i++) { //여행 도시 정보 저장 16 | route[i] = sc.nextInt(); 17 | } 18 | parent = new int[N + 1]; 19 | for (int i = 1; i <= N; i++) { //대표 노드를 자기 자신으로 초기화 20 | parent[i] = i; 21 | } 22 | for (int i = 1; i <= N; i++) { //인접행렬 탐색에서 도시가 연결되어있으면 유니온 실행 23 | for (int j = 1; j <= N; j++) { 24 | if (dosi[i][j] == 1) union(i, j); 25 | } 26 | } 27 | // 여행 계획 도시들이 하나의 대표 도시로 연결되어있는지 확인 28 | int index = find(route[1]); 29 | for (int i = 2; i < route.length; i++) { 30 | if (index != find(route[i])) { 31 | System.out.println("NO"); 32 | return; 33 | } 34 | } 35 | System.out.println("YES"); 36 | } 37 | public static void union(int a, int b) { // union 연산 : 대표 노드끼리 연결하여 줌 38 | a = find(a); 39 | b = find(b); 40 | if (a != b) { 41 | parent[b] = a; 42 | } 43 | } 44 | public static int find(int a) { // find 연산 45 | if (a == parent[a]) 46 | return a; 47 | else 48 | return parent[a] = find(parent[a]); // 재귀함수의 형태로 구현 -> 경로 압축 부분 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /그래프/P2251_물통.java: -------------------------------------------------------------------------------- 1 | import java.util.LinkedList; 2 | import java.util.Queue; 3 | import java.util.Scanner; 4 | public class P2251_물통 { 5 | // 6가지의 이동 케이스를 표현하기 위한 배열 6 | static int[] Sender = { 0, 0, 1, 1, 2, 2 }; 7 | static int[] Receiver = { 1, 2, 0, 2, 0, 1 }; 8 | static boolean visited[][]; //A B의 무게만 있으면 C의 무게가 고정되므로 2개로만 체크 가능 9 | static boolean answer[]; 10 | static int now[]; 11 | public static void main(String[] args) { 12 | Scanner scan = new Scanner(System.in); 13 | now = new int[3]; // A B C 물의 양을 저장하는 배열 14 | now[0] = scan.nextInt(); 15 | now[1] = scan.nextInt(); 16 | now[2] = scan.nextInt(); 17 | visited = new boolean[201][201]; 18 | answer = new boolean[201]; 19 | BFS(); 20 | for (int i = 0; i < answer.length; i++) { 21 | if (answer[i]) System.out.print(i + " "); 22 | } 23 | } 24 | public static void BFS() { 25 | Queue queue = new LinkedList<>(); 26 | queue.add(new AB(0, 0)); 27 | visited[0][0] = true; 28 | answer[now[2]] = true; 29 | while (!queue.isEmpty()) { 30 | AB p = queue.poll(); 31 | int A = p.A; 32 | int B = p.B; 33 | int C = now[2] - A - B; // C는 전체 물의 양에서 A와 B를 빼준 것 34 | for (int k = 0; k < 6; k++) { // A->B, A->C, B->A, B->C, C->A, C->B 6개의 케이스로 이동 35 | int[] next = { A, B, C }; 36 | next[Receiver[k]] += next[Sender[k]]; 37 | next[Sender[k]] = 0; 38 | if (next[Receiver[k]] > now[Receiver[k]]) { // 대상 물통의 용량보다 물이 많아 넘칠 때 39 | // 초과하는 만큼 다시 이전 물통에 넣어줌 40 | next[Sender[k]] = next[Receiver[k]] - now[Receiver[k]]; 41 | next[Receiver[k]] = now[Receiver[k]]; // 대상 물통은 최대로 채워줌 42 | } 43 | if (!visited[next[0]][next[1]]) { // A와 B의 물의 양을 통하여 방문 배열 체크 44 | visited[next[0]][next[1]] = true; 45 | queue.add(new AB(next[0], next[1])); 46 | if (next[0] == 0) { // A의 물의 양이 0일때 C의 물의 무게를 정답 변수에 저장 47 | answer[next[2]] = true; 48 | } 49 | } 50 | } 51 | } 52 | } 53 | } 54 | //AB 클래스선언 -> A와 B의 값만 가지고 있으면 C는 유추가 가능하기 때문에 두 변수만 사용 55 | class AB { 56 | int A; 57 | int B; 58 | public AB(int A, int B) { 59 | this.A = A; 60 | this.B = B; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /그래프/P2252_줄세우기.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.LinkedList; 3 | import java.util.Queue; 4 | import java.util.Scanner; 5 | public class P2252_줄세우기 { 6 | public static void main(String[] args) throws Exception { 7 | Scanner sc = new Scanner(System.in); 8 | int N = sc.nextInt(); 9 | int M = sc.nextInt(); 10 | ArrayList> A = new ArrayList<>(); 11 | for (int i = 0; i <= N; i++) { 12 | A.add(new ArrayList<>()); 13 | } 14 | int[] indegree = new int[N + 1]; // 진입 차수 배열 15 | for (int i = 0; i < M; i++) { 16 | int S = sc.nextInt(); 17 | int E = sc.nextInt(); 18 | A.get(S).add(E); 19 | indegree[E]++; // 진입차수 배열 데이터 저장하기 20 | } 21 | Queue queue = new LinkedList<>(); // 위상 정렬 수행 22 | for (int i = 1; i <= N; i++) { 23 | if (indegree[i] == 0) { 24 | queue.offer(i); 25 | } 26 | } 27 | while (!queue.isEmpty()) { 28 | int now = queue.poll(); 29 | System.out.print(now + " "); 30 | for (int next : A.get(now)) { 31 | indegree[next]--; 32 | if (indegree[next] == 0) { 33 | queue.offer(next); 34 | } 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /그리디/P11047_동전개수최솟값.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | public class P11047_동전개수최솟값 { 3 | public static void main(String[] args) { 4 | Scanner sc = new Scanner(System.in); 5 | int N = sc.nextInt(); 6 | int K = sc.nextInt(); 7 | int[] A = new int[N]; 8 | for (int i = 0; i < N; i++) { 9 | A[i] = sc.nextInt(); 10 | } 11 | int count = 0; 12 | for (int i = N - 1; i >= 0; i--) { 13 | if (A[i] <= K) { // 현재 동전의 가치가 K보다 작거나 같으면 구성에 추가한다. 14 | count += (K / A[i]); 15 | K = K % A[i]; // K를 현재 동전을 사용하고 남은 금액으로 업데이트 함 16 | } 17 | } 18 | System.out.println(count); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /그리디/P1541_잃어버린괄호.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | public class P1541_잃어버린괄호 { 3 | static int answer = 0; 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | String example = sc.nextLine(); 7 | String[] str = example.split("-"); 8 | for (int i = 0; i < str.length; i++) { 9 | int temp = mySum(str[i]); 10 | if (i == 0) 11 | answer = answer + temp; // 제일 앞에 것만 더해주고 12 | else 13 | answer = answer - temp; // 뒤에 부분은 더한 값들을 빼줌 14 | } 15 | System.out.println(answer); 16 | } 17 | static int mySum(String a) { // 나눠진 그룹의 더하기 연산 수행 함수 18 | int sum = 0; 19 | String temp[] = a.split("[+]"); 20 | for (int i = 0; i < temp.length; i++) { 21 | sum += Integer.parseInt(temp[i]); 22 | } 23 | return sum; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /그리디/P1715_카드정렬하기.java: -------------------------------------------------------------------------------- 1 | import java.util.PriorityQueue; 2 | import java.util.Scanner; 3 | 4 | public class P1715_카드정렬하기 { 5 | public static void main(String[] args) { 6 | Scanner sc = new Scanner(System.in); 7 | int N = sc.nextInt(); // 카드 묶음의 수 저장 8 | PriorityQueue pq = new PriorityQueue<>(); 9 | for (int i = 0; i < N; i++) { 10 | int data = sc.nextInt(); 11 | pq.add(data); 12 | } 13 | int data1 = 0; 14 | int data2 = 0; 15 | int sum = 0; 16 | while (pq.size() != 1) { 17 | data1 = pq.remove(); 18 | data2 = pq.remove(); 19 | sum += data1 + data2; 20 | pq.add(data1 + data2); 21 | } 22 | System.out.println(sum); 23 | } 24 | } -------------------------------------------------------------------------------- /그리디/P1744_수묶기.java: -------------------------------------------------------------------------------- 1 | import java.util.Collections; 2 | import java.util.PriorityQueue; 3 | import java.util.Scanner; 4 | public class P1744_수묶기 { 5 | public static void main(String[] args) { 6 | Scanner sc = new Scanner(System.in); 7 | int N = sc.nextInt(); // 카드 묶음의 수 저장 8 | // 양수는 내림차순 정렬 9 | PriorityQueue plusPq = new PriorityQueue<>(Collections.reverseOrder()); 10 | PriorityQueue minusPq = new PriorityQueue<>(); 11 | int one = 0; 12 | int zero = 0; 13 | for (int i = 0; i < N; i++) { // 4개의 그룹으로 분리하여 저장 14 | int data = sc.nextInt(); 15 | if (data > 1) { 16 | plusPq.add(data); 17 | } else if (data == 1) { 18 | one++; 19 | } else if (data == 0) { 20 | zero++; 21 | } else { 22 | minusPq.add(data); 23 | } 24 | } 25 | int sum = 0; 26 | // 양수처리 27 | while (plusPq.size() > 1) { 28 | int first = plusPq.remove(); 29 | int second = plusPq.remove(); 30 | sum = sum + first * second; 31 | } 32 | if (!plusPq.isEmpty()) { 33 | sum = sum + plusPq.remove(); 34 | } 35 | // 음수처리 36 | while (minusPq.size() > 1) { 37 | int first = minusPq.remove(); 38 | int second = minusPq.remove(); 39 | sum = sum + first * second; 40 | } 41 | if (!minusPq.isEmpty()) { 42 | if (zero == 0) { 43 | sum = sum + minusPq.remove(); 44 | } 45 | } 46 | // 1처리 47 | sum = sum + one; 48 | System.out.println(sum); 49 | } 50 | } -------------------------------------------------------------------------------- /그리디/P1931_회의실배정.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | import java.util.Comparator; 3 | import java.util.Scanner; 4 | public class P1931_회의실배정 { 5 | public static void main(String[] args) { 6 | Scanner sc = new Scanner(System.in); 7 | int N = sc.nextInt(); 8 | int[][] A = new int[N][2]; 9 | for (int i = 0; i < N; i++) { 10 | A[i][0] = sc.nextInt(); 11 | A[i][1] = sc.nextInt(); 12 | } 13 | Arrays.sort(A, new Comparator() { 14 | @Override 15 | public int compare(int[] S, int[] E) { 16 | if (S[1] == E[1]) { // 종료 시간이 같을 경우 17 | return S[0] - E[0]; 18 | } 19 | return S[1] - E[1]; 20 | } 21 | }); 22 | int count = 0; 23 | int end = -1; 24 | for (int i = 0; i < N; i++) { 25 | if (A[i][0] >= end) { // 겹치지 않는 다음 회의가 나온경우 26 | end = A[i][1]; // 종료시간 업데이트 27 | count++; 28 | } 29 | } 30 | 31 | System.out.println(count); 32 | } 33 | } -------------------------------------------------------------------------------- /기하/P11758_CCW.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.util.StringTokenizer; 3 | public class P11758_CCW { 4 | public static void main(String[] args) throws Exception { 5 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 6 | StringTokenizer st = new StringTokenizer(br.readLine()); 7 | int x1 = Integer.parseInt(st.nextToken()); 8 | int y1 = Integer.parseInt(st.nextToken()); 9 | st = new StringTokenizer(br.readLine()); 10 | int x2 = Integer.parseInt(st.nextToken()); 11 | int y2 = Integer.parseInt(st.nextToken()); 12 | st = new StringTokenizer(br.readLine()); 13 | int x3 = Integer.parseInt(st.nextToken()); 14 | int y3 = Integer.parseInt(st.nextToken()); 15 | int result = (x1 * y2 + x2 * y3 + x3 * y1) - (x2 * y1 + x3 * y2 + x1 * y3); 16 | int ans = 0; 17 | if (result > 0) { 18 | ans = 1; 19 | } else if (result < 0) { 20 | ans = -1; 21 | } else { 22 | ans = 0; 23 | } 24 | System.out.println(ans); 25 | } 26 | } -------------------------------------------------------------------------------- /기하/P17387_선분교차.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.util.StringTokenizer; 3 | public class P17387_선분교차 { 4 | public static void main(String[] args) throws Exception { 5 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 6 | StringTokenizer st = new StringTokenizer(br.readLine()); 7 | long x1 = Integer.parseInt(st.nextToken()); 8 | long y1 = Integer.parseInt(st.nextToken()); 9 | long x2 = Integer.parseInt(st.nextToken()); 10 | long y2 = Integer.parseInt(st.nextToken()); 11 | st = new StringTokenizer(br.readLine()); 12 | long x3 = Integer.parseInt(st.nextToken()); 13 | long y3 = Integer.parseInt(st.nextToken()); 14 | long x4 = Integer.parseInt(st.nextToken()); 15 | long y4 = Integer.parseInt(st.nextToken()); 16 | boolean cross = isCross(x1, y1, x2, y2, x3, y3, x4, y4); 17 | if (cross)System.out.println(1); 18 | else System.out.println(0); 19 | } 20 | static int CCW(long x1, long y1, long x2, long y2, long x3, long y3) { 21 | long temp = (x1 * y2 + x2 * y3 + x3 * y1) - (x2 * y1 + x3 * y2 + x1 * y3); 22 | if(temp > 0) return 1; 23 | else if(temp < 0) return -1; 24 | return 0; 25 | } 26 | //선분겹침여부 판별 함수 27 | private static boolean isOverlab(long x1,long y1,long x2,long y2,long x3,long y3,long x4,long y4){ 28 | if(Math.min(x1, x2) <= Math.max(x3, x4) && Math.min(x3, x4) <= Math.max(x1, x2) 29 | && Math.min(y1, y2) <= Math.max(y3, y4) && Math.min(y3, y4) <= Math.max(y1, y2))return true; 30 | return false; 31 | } 32 | private static boolean isCross(long x1,long y1,long x2,long y2,long x3,long y3,long x4,long y4) { 33 | int abc = CCW(x1, y1, x2, y2, x3, y3); 34 | int abd = CCW(x1, y1, x2, y2, x4, y4); 35 | int cda = CCW(x3, y3, x4, y4, x1, y1); 36 | int cdb = CCW(x3, y3, x4, y4, x2, y2); 37 | if(abc * abd == 0 && cda * cdb == 0) { // 선분이 일직 선인 경우 38 | return isOverlab(x1, y1, x2, y2, x3, y3, x4, y4); //겹치는 선분인지 판별하기 39 | }else if(abc * abd <= 0 && cda * cdb <= 0) { // 선분이 교차하는 경우 40 | return true; 41 | } 42 | return false; 43 | }} -------------------------------------------------------------------------------- /기하/P2162_선분그룹.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.util.StringTokenizer; 3 | public class P2162_선분그룹 { 4 | static int parent[] = new int[3001]; 5 | static int L[][] = new int[3001][4]; 6 | public static void main(String[] args) throws Exception { 7 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 8 | StringTokenizer st = new StringTokenizer(br.readLine()); 9 | int N = Integer.parseInt(st.nextToken()); 10 | for (int i = 1; i <= N; i++) { 11 | parent[i] = -1; 12 | } 13 | for (int i = 1; i <= N; i++) { 14 | st = new StringTokenizer(br.readLine()); 15 | L[i][0] = Integer.parseInt(st.nextToken()); 16 | L[i][1] = Integer.parseInt(st.nextToken()); 17 | L[i][2] = Integer.parseInt(st.nextToken()); 18 | L[i][3] = Integer.parseInt(st.nextToken()); 19 | for (int j = 1; j < i; j++) { //이전에 저장된 선분들과 교차 여부 확인 20 | if (isCross(L[i][0], L[i][1], L[i][2], L[i][3], L[j][0], L[j][1], L[j][2], L[j][3]) == true) { 21 | Union(i, j); 22 | } 23 | } 24 | } 25 | int ans = 0, res=0; 26 | for (int i = 1; i <= N; i++) { 27 | if (parent[i] < 0) { //음수이면 선분그룹을 대표하는 부모(대표) 노드이므로 카운트 28 | ans++; 29 | res = Math.min(res, parent[i]); //음수의 절대 값이 선분그룹의 선분 개수 30 | } 31 | } 32 | System.out.println(ans); 33 | System.out.println(-res); 34 | } 35 | private static int find(int i) { 36 | if (parent[i] < 0) 37 | return i; 38 | return parent[i] = find(parent[i]); 39 | } 40 | private static void Union(int i, int j) { 41 | int p = find(i); 42 | int q = find(j); 43 | if (p == q) 44 | return; 45 | parent[p] += parent[q]; 46 | parent[q] = p; 47 | } 48 | static int CCW(long x1, long y1, long x2, long y2, long x3, long y3) { 49 | long temp = (x1 * y2 + x2 * y3 + x3 * y1) - (x2 * y1 + x3 * y2 + x1 * y3); 50 | if (temp > 0) 51 | return 1; 52 | else if (temp < 0) 53 | return -1; 54 | return 0; 55 | } 56 | private static boolean isOverlab(long x1,long y1,long x2,long y2,long x3,long y3,long x4,long y4) { 57 | if (Math.min(x1, x2) <= Math.max(x3, x4) && Math.min(x3, x4) <= Math.max(x1, x2) 58 | && Math.min(y1, y2) <= Math.max(y3, y4) && Math.min(y3, y4) <= Math.max(y1, y2)) 59 | return true; 60 | return false; 61 | } 62 | private static boolean isCross(long x1,long y1,long x2,long y2,long x3,long y3,long x4,long y4) { 63 | int abc = CCW(x1, y1, x2, y2, x3, y3); 64 | int abd = CCW(x1, y1, x2, y2, x4, y4); 65 | int cda = CCW(x3, y3, x4, y4, x1, y1); 66 | int cdb = CCW(x3, y3, x4, y4, x2, y2); 67 | if (abc * abd == 0 && cda * cdb == 0) { // 선분이 일직 선인 경우 68 | return isOverlab(x1, y1, x2, y2, x3, y3, x4, y4); 69 | } else if (abc * abd <= 0 && cda * cdb <= 0) { // 선분이 교차하는 경우 70 | return true; 71 | } 72 | return false; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /기하/P2166_다각형의넓이.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | public class P2166_다각형의넓이 { 3 | public static void main(String[] args) { 4 | Scanner sc = new Scanner(System.in); 5 | int N = sc.nextInt(); 6 | long[] x = new long[N + 1]; 7 | long[] y = new long[N + 1]; 8 | for (int i = 0; i < N; i++) { 9 | x[i] = sc.nextInt(); 10 | y[i] = sc.nextInt(); 11 | } 12 | x[N] = x[0]; // 마지막과 처음점도 CCW 계산에 포함해주어야함 13 | y[N] = y[0]; 14 | double result = 0; 15 | for (int i = 0; i < N; i++) { 16 | result += (x[i] * y[i + 1]) - (x[i + 1] * y[i]); 17 | } 18 | String answer = String.format("%.1f", Math.abs(result) / 2.0); // 둘째 자리 반올림 19 | System.out.println(answer); 20 | } 21 | } -------------------------------------------------------------------------------- /동적계획법/P10844_계단수.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | public class P10844_계단수 { 3 | static long mod = 1000000000; 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | int N = sc.nextInt(); 7 | long D[][] = new long[N + 1][11]; 8 | for (int i = 1; i <= 9; i++) { // 0으로 숫자가 시작 할 수 없으므로 D[0][1]은 0으로 초기화 9 | D[1][i] = 1; 10 | } 11 | for (int i = 2; i <= N; i++) { 12 | D[i][0] = D[i - 1][1]; 13 | D[i][9] = D[i - 1][8]; 14 | for (int j = 1; j <= 8; j++) { 15 | D[i][j] = (D[i - 1][j - 1] + D[i - 1][j + 1]) % mod; 16 | } 17 | } 18 | long sum = 0; 19 | for (int i = 0; i < 10; i++) { 20 | sum = (sum + D[N][i]) % mod; //정답 값을 더해 줄 때도 %연산 수행 21 | } 22 | System.out.println(sum); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /동적계획법/P11049_행렬곱연산횟수의최솟값.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | import java.io.*; 3 | public class P11049_행렬곱연산횟수의최솟값 { 4 | static int N; 5 | static Matrix[] M; 6 | static int[][] D; 7 | public static void main(String args[]) throws IOException { 8 | Scanner sc = new Scanner(System.in); 9 | N = sc.nextInt(); 10 | M = new Matrix[N + 1]; 11 | D = new int[N + 1][N + 1]; 12 | for (int i = 0; i < D.length; i++) 13 | for (int j = 0; j < D[i].length; j++) 14 | D[i][j] = -1; 15 | for (int i = 1; i <= N; i++) { 16 | int y = sc.nextInt(); 17 | int x = sc.nextInt(); 18 | M[i] = new Matrix(y, x); 19 | } 20 | System.out.println(excute(1, N)); 21 | } 22 | // top-down방식 점화식 함수 구현 23 | static int excute(int s, int e) { 24 | int result = Integer.MAX_VALUE; 25 | if (D[s][e] != -1) // 이미 계산한 적이 있는 부분이면 다시 계산하지 않는다 -> 메모이제이션 26 | return D[s][e]; 27 | if (s == e) // 행렬 한 개의 곱셈 연산의 수 28 | return 0; 29 | if (s + 1 == e) // 행렬 두 개의 곱셈 연산의 수 30 | return M[s].y * M[s].x * M[e].x; 31 | for (int i = s; i < e; i++) // 행렬이 3개 이상일 경우 곱셈연산수 -> 점화식 처리 32 | result = Math.min(result, M[s].y * M[i].x * M[e].x + excute(s, i) + excute(i + 1, e)); 33 | return D[s][e] = result; 34 | } 35 | // 행렬정보 저장 Class 36 | static class Matrix { 37 | private int y; 38 | private int x; 39 | Matrix(int y, int x) { 40 | this.y = y; 41 | this.x = x; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /동적계획법/P11726_타일채우기.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | public class P11726_타일채우기 { 3 | static long mod = 10007; 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | int N = sc.nextInt(); 7 | long D[] = new long[1001]; 8 | D[1] = 1; //길이가 2*1일때 타일 경우의 수 9 | D[2] = 2; //길이가 2*2일때 타일 경우의 수 10 | for(int i=3; i<=N; i++){ 11 | D[i] = (D[i-1] + D[i-2])%mod; 12 | } 13 | System.out.println(D[N]); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /동적계획법/P1328_빌딩.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | public class P1328_빌딩 { 3 | static long mod = 1000000007; 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | int N = sc.nextInt(); 7 | int L = sc.nextInt(); 8 | int R = sc.nextInt(); 9 | long D[][][] = new long[101][101][101]; 10 | D[1][1][1] = 1; // 빌딩이 1개이면 놓은 수 있는 경우의 수는 1개 11 | for (int i = 2; i <= N; i++) { 12 | for (int j = 1; j <= L; j++) { 13 | for (int k = 1; k <= R; k++) { 14 | D[i][j][k] = (D[i - 1][j][k] * (i - 2) + (D[i - 1][j][k - 1] + D[i - 1][j - 1][k])) % mod; 15 | } 16 | } 17 | } 18 | System.out.println(D[N][L][R]); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /동적계획법/P13398_연속된정수의합.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.util.StringTokenizer; 3 | 4 | public class P13398_연속된정수의합 { 5 | public static void main(String[] args) throws IOException { 6 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 7 | BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); 8 | int N = Integer.parseInt(br.readLine()); 9 | StringTokenizer st = new StringTokenizer(br.readLine()); 10 | int[] A = new int[N]; 11 | for (int i = 0; i < N; i++) { 12 | A[i] = Integer.parseInt(st.nextToken()); 13 | } 14 | // 오른쪽 방향으로 index를 포함한 최대 연속 합 구하기. 15 | int[] L = new int[N]; 16 | L[0] = A[0]; 17 | int result = L[0]; 18 | for (int i = 1; i < N; i++) { 19 | L[i] = Math.max(A[i], L[i - 1] + A[i]); 20 | result = Math.max(result, L[i]); // 하나도 제거 하지 않았을 때를 기본 최대값으로 저장 21 | } 22 | // 왼쪽 방향으로 index를 포함한 최대 연속 합 구하기. 23 | int[] R = new int[N]; 24 | R[N - 1] = A[N - 1]; 25 | for (int i = N - 2; i >= 0; i--) { 26 | R[i] = Math.max(A[i], R[i + 1] + A[i]); 27 | } 28 | // L[i - 1] + R[i + 1] 두개의 구간합 배열을 더해주면 i번째 값을 제거한 효과를 얻음 29 | for (int i = 1; i < N - 1; i++) { 30 | int temp = L[i - 1] + R[i + 1]; 31 | result = Math.max(result, temp); 32 | } 33 | bw.write(result + "\n"); 34 | bw.flush(); 35 | bw.close(); 36 | br.close(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /동적계획법/P14003_가장길게증가하는부분수열.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.util.StringTokenizer; 3 | public class P14003_가장길게증가하는부분수열 { 4 | static int N, maxLength; 5 | static int B[] = new int[1000001]; 6 | static int A[] = new int[1000001]; 7 | static int D[] = new int[1000001]; 8 | static int ans[] = new int[1000001]; 9 | public static void main(String[] args) throws IOException { 10 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 11 | N = Integer.parseInt(br.readLine()); 12 | StringTokenizer st = new StringTokenizer(br.readLine()); 13 | for (int i = 1; i <= N; i++) { 14 | A[i] = Integer.parseInt(st.nextToken()); 15 | } 16 | int index; 17 | B[++maxLength] = A[1]; 18 | D[1] = 1; 19 | for (int i = 2; i <= N; i++) { 20 | if (B[maxLength] < A[i]) { //가장 마지막 수열보다 현재 수열이 큰 경우 21 | B[++maxLength] = A[i]; 22 | D[i] = maxLength; 23 | } else { 24 | index = binarysearch(1, maxLength, A[i]); // B배열에서 data[i]보다 처음으로 크거나 같아지는 원소의 index 찾기 25 | B[index] = A[i]; 26 | D[i] = index; 27 | } 28 | } 29 | System.out.println(maxLength); //가장 긴 증가하는 부분 수열 길이 출력 30 | index = maxLength; 31 | int x = B[maxLength] + 1; 32 | for (int i = N; i >= 1; i--) { //뒤에서 부터 탐색하면서 정답 수열 저장하기 33 | if (D[i] == index && A[i] < x) { 34 | ans[index] = A[i]; 35 | x = A[i]; 36 | index--; 37 | } 38 | } 39 | for (int i = 1; i <= maxLength; i++) 40 | System.out.print(ans[i] + " "); 41 | } 42 | // 현재 수열이 들어 갈 수 있는 위치를 빠르게 찾아주기 위한 바이너리 서치 구현 43 | static int binarysearch(int l, int r, int now) { 44 | int mid; 45 | while (l < r) { 46 | mid = (l + r) / 2; 47 | if (B[mid] < now) 48 | l = mid + 1; 49 | else 50 | r = mid; 51 | } 52 | return l; 53 | } 54 | } -------------------------------------------------------------------------------- /동적계획법/P14501_퇴사.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | public class P14501_퇴사 { 3 | public static void main(String[] args) { 4 | // TODO Auto-generated method stub 5 | Scanner sc = new Scanner(System.in); 6 | int N = sc.nextInt(); 7 | int[] D = new int[N+2]; //오늘부터 퇴사일까지 벌수있는 최대 수입 8 | int[] T = new int[N+1]; 9 | int[] P = new int[N+1]; 10 | for(int i=1; i<=N; i++) 11 | { 12 | T[i] = sc.nextInt(); 13 | P[i] = sc.nextInt(); 14 | } 15 | for(int i=N;i>0;i--) { 16 | if(i+T[i]>N+1) { 17 | D[i]=D[i+1]; 18 | } 19 | else { 20 | D[i]=Math.max(D[i+1],P[i]+D[i+T[i]]); 21 | } 22 | } 23 | System.out.println(D[1]); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /동적계획법/P1463_1로만들기.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class P1463_1로만들기 { 3 | static int N; 4 | static int D[]; 5 | public static void main(String[] args) throws Exception { 6 | Scanner sc = new Scanner(System.in); 7 | N = sc.nextInt(); 8 | D = new int[N + 1]; 9 | D[1] = 0; 10 | for (int i = 2; i <= N; i++) { 11 | D[i] = D[i-1]+1; 12 | if(i%2==0)D[i]=Math.min(D[i], D[i/2]+1); 13 | if(i%3==0)D[i]=Math.min(D[i], D[i/3]+1); 14 | } 15 | System.out.println(D[N]); 16 | } 17 | } -------------------------------------------------------------------------------- /동적계획법/P1915_가장큰정사각형.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | public class P1915_가장큰정사각형 { 3 | public static void main(String[] args) { 4 | long[][] D = new long[1001][1001]; 5 | Scanner sc = new Scanner(System.in); 6 | int n = sc.nextInt(); 7 | int m = sc.nextInt(); 8 | long max = 0; 9 | for (int i = 0; i < n; i++) { 10 | String mline = sc.next(); 11 | for (int j = 0; j < m; j++) { 12 | D[i][j] = Long.parseLong(String.valueOf(mline.charAt(j))); 13 | if (D[i][j] == 1 && j > 0 && i > 0) { 14 | D[i][j] = Math.min(D[i - 1][j - 1], Math.min(D[i - 1][j], D[i][j - 1])) + D[i][j]; 15 | } 16 | if (max < D[i][j]) { 17 | max = D[i][j]; 18 | } 19 | } 20 | } 21 | System.out.println(max * max); 22 | } 23 | } -------------------------------------------------------------------------------- /동적계획법/P2098_외판원순회.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedReader; 2 | import java.io.InputStreamReader; 3 | import java.util.StringTokenizer; 4 | class P2098_외판원순회 { 5 | private static final int INF = 1000000*16+1; 6 | private static int N; 7 | private static int[][] W; 8 | private static int[][] d; 9 | public static void main(String[] args) throws Exception { 10 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 11 | StringTokenizer st = null; 12 | N = Integer.parseInt(br.readLine().trim()); 13 | W = new int[16][16]; 14 | for (int i = 0; i < N; i++) { 15 | st = new StringTokenizer(br.readLine().trim()); 16 | for (int j = 0; j < N; j++) { 17 | W[i][j] = Integer.parseInt(st.nextToken()); 18 | } 19 | } 20 | d = new int[16][1 << 16]; 21 | for (int i = 0; i < N; i++) { 22 | for (int j = 0; j < 1 << N; j++) { 23 | d[i][j] = INF; //모든 비용을 충분히 큰수로 저장 24 | } 25 | } 26 | System.out.println(tsp(0, 1)); 27 | } 28 | private static int tsp(int c, int v) { //모든 경우의 수에 대한 완전 탐색, 재귀 구현 29 | if (v == (1 << N) - 1) { // 모든 노드를 방문한 경우 30 | return W[c][0] == 0 ? INF : W[c][0]; 31 | } 32 | if (d[c][v] != INF) { //이미 방문한 노드인 경우 -> 이미 계산한 경우 바로 리턴 (메모이제이션) 33 | return d[c][v]; 34 | } 35 | for (int i = 0; i < N; i++) { 36 | if ((v & (1 << i)) == 0 && W[c][i] != 0) { //방문한적이 없고 갈 수 있는 도시인 경우 37 | d[c][v] = Math.min(d[c][v], tsp(i, (v | (1 << i))) + W[c][i]); 38 | } 39 | } 40 | return d[c][v]; 41 | } 42 | } -------------------------------------------------------------------------------- /동적계획법/P2098_외판원순회_시간초과해결버전.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedReader; 2 | import java.io.InputStreamReader; 3 | import java.util.StringTokenizer; 4 | class P2098_외판원순회_시간초과해결버전 { 5 | private static int N; 6 | private static int[][] W; 7 | private static int[][] d; 8 | private static final int INF = 1000000*16+1; 9 | public static void main(String[] args) throws Exception { 10 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 11 | StringTokenizer st = null; 12 | N = Integer.parseInt(br.readLine().trim()); 13 | W = new int[16][16]; 14 | d = new int[16][1 << 16]; 15 | for (int i = 0; i < N; i++) { 16 | st = new StringTokenizer(br.readLine().trim()); 17 | for (int j = 0; j < N; j++) { 18 | W[i][j] = Integer.parseInt(st.nextToken()); 19 | } 20 | } 21 | System.out.println(tsp(0, 1)); 22 | } 23 | private static int tsp(int c, int v) { //모든 경우의 수에 대한 완전 탐색, 재귀 구현 24 | if (v == (1 << N) - 1) { // 모든 노드를 방문한 경우 25 | return W[c][0] == 0 ? INF : W[c][0]; 26 | } 27 | if (d[c][v] != 0) { //이미 방문한 노드인 경우 -> 이미 계산한 경우 바로 리턴 (메모이제이션) 28 | return d[c][v]; 29 | } 30 | int min_val = INF; 31 | for (int i = 0; i < N; i++) { 32 | if ((v & (1 << i)) == 0 && W[c][i] != 0) { //방문한적이 없고 갈 수 있는 도시인 경우 33 | min_val = Math.min(min_val, tsp(i, (v | (1 << i))) + W[c][i]); 34 | } 35 | } 36 | d[c][v] = min_val; 37 | return d[c][v]; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /동적계획법/P2193_이친수.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | public class P2193_이친수 { 3 | public static void main(String[] args) { 4 | Scanner sc = new Scanner(System.in); 5 | int N = sc.nextInt(); 6 | long D[][] = new long[N+1][2]; 7 | D[1][1] = 1; 8 | D[1][0] = 0; 9 | for(int i=2; i<=N; i++){ 10 | D[i][0] = D[i-1][1] + D[i-1][0]; 11 | D[i][1] = D[i-1][0]; 12 | } 13 | System.out.println(D[N][0] + D[N][1]); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /동적계획법/P2342_DDR.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | public class P2342_DDR { 3 | public static void main(String[] args) throws Exception { 4 | Scanner sc = new Scanner(System.in); 5 | //dp[N][L][R] = N개 수열을 수행하였고 왼쪽이 L 오른쪽이 R자리에 있을때 최소 누적 힘 6 | int dp[][][] = new int[100001][5][5]; 7 | //한발을 이동할 때 드는 힘을 미리 저장해 두기 mp[1][2] -> 1에서 2로 이동할때 드는 힘 8 | int mp[][] = { { 0, 2, 2, 2, 2 }, 9 | { 2, 1, 3, 4, 3 }, 10 | { 2, 3, 1, 3, 4 }, 11 | { 2, 4, 3, 1, 3 }, 12 | { 2, 3, 4, 3, 1 } }; 13 | int n = 0, s = 1; 14 | for (int i = 0; i < 5; i++) 15 | for (int j = 0; j < 5; j++) 16 | for (int k = 0; k < 100001; k++) 17 | dp[k][i][j] = 100001 * 4; //충분히 큰수로 초기화 18 | dp[0][0][0] = 0; 19 | while (true) { 20 | n = sc.nextInt(); 21 | if (n == 0) // 입력의 마지막이면 종료 22 | break; 23 | for (int i = 0; i < 5; i++) { 24 | if (n == i) //두발이 같은 자리에 있을 수 없음 25 | continue; 26 | for (int j = 0; j < 5; j++) { 27 | // 오른발을 옮겨서 현재 모습이 되었을 때 최소의 힘 저장 28 | dp[s][i][n] = Math.min(dp[s - 1][i][j] + mp[j][n], dp[s][i][n]); 29 | } 30 | } 31 | for (int j = 0; j < 5; j++) { 32 | if (n == j) //두발이 같은 자리에 있을 수 없음 33 | continue; 34 | for (int i = 0; i < 5; i++) { 35 | //왼발을 옮겨서 현재 모습이 되었을 때 최소의 힘 저장 36 | dp[s][n][j] = Math.min(dp[s - 1][i][j] + mp[i][n], dp[s][n][j]); 37 | } 38 | } 39 | s++; 40 | } 41 | s--; 42 | int min = Integer.MAX_VALUE; 43 | for (int i = 0; i < 5; i++) 44 | for (int j = 0; j < 5; j++) 45 | min = Math.min(min, dp[s][i][j]); //모두 수행하였을 때 최소 값 찾기 46 | System.out.println(min); //최소값 출력 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /동적계획법/P2747_피보나치수_BottomUp.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | public class P2747_피보나치수_BottomUp { 3 | static int[] D; 4 | public static void main(String[] args) { 5 | // TODO Auto-generated method stub 6 | Scanner sc = new Scanner(System.in); 7 | int n = sc.nextInt(); 8 | D = new int[n + 1]; 9 | for (int i = 0; i <= n; i++) { 10 | D[i] = -1; 11 | } 12 | D[0] = 0; 13 | D[1] = 1; 14 | for (int i = 2; i <= n; i++) { 15 | D[i] = D[i - 1] + D[i - 2]; 16 | } 17 | System.out.println(D[n]); 18 | } 19 | } -------------------------------------------------------------------------------- /동적계획법/P2747_피보나치수_TopDown.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | 3 | public class P2747_피보나치수_TopDown { 4 | static int[] D; 5 | public static void main(String[] args) { 6 | // TODO Auto-generated method stub 7 | Scanner sc = new Scanner(System.in); 8 | int n = sc.nextInt(); 9 | D = new int[n + 1]; 10 | for (int i = 0; i <= n; i++) { 11 | D[i] = -1; 12 | } 13 | D[0] = 0; 14 | D[1] = 1; 15 | fibo(n); 16 | System.out.println(D[n]); 17 | } 18 | 19 | static int fibo(int n) { 20 | if (D[n] != -1) //기존에 계산한 적이 있는 부분 문제는 다시 계산하지 않고 리턴한다. 21 | return D[n]; 22 | return D[n] = fibo(n - 2) + fibo(n - 1); //메모이제이션 부분 23 | } 24 | } -------------------------------------------------------------------------------- /동적계획법/P9252_LCS.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.util.ArrayList; 3 | public class P9252_LCS { 4 | private static long[][] DP; 5 | private static ArrayList Path; 6 | private static char[] A; 7 | private static char[] B; 8 | public static void main(String[] args) throws Exception { 9 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 10 | A = br.readLine().toCharArray(); 11 | B = br.readLine().toCharArray(); 12 | DP = new long[A.length + 1][B.length + 1]; 13 | Path = new ArrayList(); 14 | for (int i = 1; i <= A.length; i++) { 15 | for (int j = 1; j <= B.length; j++) { 16 | if (A[i - 1] == B[j - 1]) { 17 | DP[i][j] = DP[i - 1][j - 1] + 1; // 같은 문자열일 경우 왼쪽 대각선 값 +1 18 | } else { 19 | DP[i][j] = Math.max(DP[i - 1][j], DP[i][j - 1]); // 다르면 왼쪽과 위의 값 중 큰수 20 | } 21 | } 22 | } 23 | System.out.println(DP[A.length][B.length]); 24 | getText(A.length, B.length); 25 | for (int i = Path.size() - 1; i >= 0; i--) { 26 | System.out.print(Path.get(i)); 27 | } 28 | System.out.println(); 29 | } 30 | private static void getText(int r, int c) { // LCS 출력함수 31 | if (r == 0 || c == 0) return; 32 | if (A[r - 1] == B[c - 1]) { // 같으면 LCS에 기록하고 왼쪽 위로 이동 33 | Path.add(A[r - 1]); 34 | getText(r - 1, c - 1); 35 | } else { 36 | if (DP[r - 1][c] > DP[r][c - 1]) // 다르면 왼쪽과 중 큰 수로 이동 37 | getText(r - 1, c); 38 | else 39 | getText(r, c - 1); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /자료구조/P10986_나머지합.java: -------------------------------------------------------------------------------- 1 | import java.io.IOException; 2 | import java.util.Scanner; 3 | public class P10986_나머지합 { 4 | public static void main(String[] args) throws IOException { 5 | Scanner sc = new Scanner(System.in); 6 | int N = sc.nextInt(); 7 | int M = sc.nextInt(); 8 | long[] S = new long[N]; 9 | long[] C = new long[M]; 10 | long answer = 0; 11 | S[0] = sc.nextInt(); 12 | for (int i = 1; i < N; i++) { // 수열 합배열 만들기 13 | S[i] = S[i - 1] + sc.nextInt(); 14 | } 15 | for (int i = 0; i < N; i++) { // 합배열의 모든 값에 %연산 수행하기 16 | int remainder = (int) (S[i] % M); 17 | if (remainder == 0) 18 | answer++; // 0~i까지의 구간합 자체가 0인 경우 정답에 더해주기 19 | C[remainder]++; // 같은 나머지를 가진 인덱스의 개수 카운팅 해주기 20 | } 21 | for (int i = 0; i < M; i++) { 22 | if (C[i] > 1) { 23 | answer = answer + (C[i] * (C[i] - 1) / 2); // 같은 나머지를 가진 인덱스들중 2개를 뽑는 경우의 수를 더해주기 24 | } 25 | } 26 | System.out.println(answer); 27 | } 28 | } -------------------------------------------------------------------------------- /자료구조/P11003_최솟값찾기.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.util.Deque; 3 | import java.util.LinkedList; 4 | import java.util.Scanner; 5 | import java.util.StringTokenizer; 6 | 7 | public class P11003_최솟값찾기 { 8 | public static final Scanner scanner = new Scanner(System.in); 9 | 10 | public static void main(String[] args) throws IOException { 11 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 12 | // 출력을 그때 그때 하는 것보다 버퍼에 넣고 한번에 출력하기 위해 BufferedWriter를 사용 13 | BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); 14 | StringTokenizer st = new StringTokenizer(br.readLine()); 15 | int N = Integer.parseInt(st.nextToken()); 16 | int L = Integer.parseInt(st.nextToken()); 17 | st = new StringTokenizer(br.readLine()); 18 | Deque mydeque = new LinkedList<>(); 19 | for (int i = 0; i < N; i++) { 20 | int now = Integer.parseInt(st.nextToken()); 21 | // 새로운 값이 들어 올 때마다 정렬하지 않고 현재 수보다 큰 값을 덱에서 제거함으로써 시간복잡도를 줄일 수 있음 22 | while (!mydeque.isEmpty() && mydeque.getLast().value > now) { 23 | mydeque.removeLast(); 24 | } 25 | mydeque.addLast(new Node(now, i)); 26 | // 범위에서 벗어난 값은 덱에서 제거 27 | if (mydeque.getFirst().index <= i - L) { 28 | mydeque.removeFirst(); 29 | } 30 | bw.write(mydeque.getFirst().value + " "); 31 | } 32 | bw.flush(); 33 | bw.close(); 34 | } 35 | 36 | static class Node { 37 | public int value; 38 | public int index; 39 | 40 | Node(int value, int index) { 41 | this.value = value; 42 | this.index = index; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /자료구조/P11268_절댓값힙.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedReader; 2 | import java.io.IOException; 3 | import java.io.InputStreamReader; 4 | import java.util.PriorityQueue; 5 | public class P11268_절댓값힙 { 6 | public static void main(String[] args) throws IOException { 7 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 8 | int N = Integer.parseInt(br.readLine()); 9 | PriorityQueue MyQueue = new PriorityQueue<>((o1, o2) -> { 10 | int first_abs = Math.abs(o1); 11 | int second_abs = Math.abs(o2); 12 | if (first_abs == second_abs) 13 | return o1 > o2 ? 1 : -1;// 절대값이 같은 경우 음수 우선 정렬 14 | else 15 | return first_abs - second_abs;// 절대값을 기준으로 정렬 16 | }); 17 | for (int i = 0; i < N; i++) { 18 | int request = Integer.parseInt(br.readLine()); 19 | if (request == 0) { 20 | if (MyQueue.isEmpty()) 21 | System.out.println("0"); 22 | else 23 | System.out.println(MyQueue.poll()); 24 | } else { 25 | MyQueue.add(request); 26 | } 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /자료구조/P11659_구간합구하기.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedReader; 2 | import java.io.IOException; 3 | import java.io.InputStreamReader; 4 | import java.util.StringTokenizer; 5 | public class P11659_구간합구하기 { 6 | public static void main(String[] args) throws IOException { 7 | BufferedReader bufferedReader 8 | = new BufferedReader(new InputStreamReader(System.in)); 9 | StringTokenizer stringTokenizer 10 | = new StringTokenizer(bufferedReader.readLine()); 11 | int suNo = Integer.parseInt(stringTokenizer.nextToken()); 12 | int quizNo = Integer.parseInt(stringTokenizer.nextToken()); 13 | long[] S = new long[suNo + 1]; 14 | stringTokenizer = new StringTokenizer(bufferedReader.readLine()); 15 | for (int i = 1; i <= suNo; i++) { 16 | S[i] = S[i - 1] + Integer.parseInt(stringTokenizer.nextToken()); 17 | } 18 | for (int q = 0; q < quizNo; q++) { 19 | stringTokenizer = new StringTokenizer(bufferedReader.readLine()); 20 | int i = Integer.parseInt(stringTokenizer.nextToken()); 21 | int j = Integer.parseInt(stringTokenizer.nextToken()); 22 | System.out.println(S[j] - S[i - 1]); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /자료구조/P11660_구간합구하기2.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedReader; 2 | import java.io.InputStreamReader; 3 | import java.util.StringTokenizer; 4 | public class P11660_구간합구하기2 { 5 | public static void main(String[] args) throws Exception { 6 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 7 | StringTokenizer st = new StringTokenizer(br.readLine()); 8 | int N = Integer.parseInt(st.nextToken()); 9 | int M = Integer.parseInt(st.nextToken()); 10 | int A[][] = new int[N + 1][N + 1]; 11 | for (int i = 1; i <= N; i++) { 12 | st = new StringTokenizer(br.readLine()); 13 | for (int j = 1; j <= N; j++) { 14 | A[i][j] = Integer.parseInt(st.nextToken()); 15 | } 16 | } 17 | int D[][] = new int[N + 1][N + 1]; 18 | for (int i = 1; i <= N; i++) { 19 | for (int j = 1; j <= N; j++) { 20 | //부분 합 구하기 21 | D[i][j] = D[i][j - 1] + D[i - 1][j] - D[i - 1][j - 1] + A[i][j]; 22 | } 23 | } 24 | for (int i = 0; i < M; i++) { 25 | st = new StringTokenizer(br.readLine()); 26 | int x1 = Integer.parseInt(st.nextToken()); 27 | int y1 = Integer.parseInt(st.nextToken()); 28 | int x2 = Integer.parseInt(st.nextToken()); 29 | int y2 = Integer.parseInt(st.nextToken()); 30 | // 부분 합 배열을 이용한 질의 답변하기 31 | int result = D[x2][y2] - D[x1 - 1][y2] - D[x2][y1 - 1] + D[x1 - 1][y1 - 1]; 32 | System.out.println(result); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /자료구조/P11720_숫자의합.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | public class P11720_숫자의합 { 3 | public static void main(String[] args) { 4 | Scanner sc = new Scanner(System.in); 5 | int N = sc.nextInt(); 6 | // String 변수로 받아 배열 변수로 변환하기 7 | String sNum = sc.next(); 8 | char[] cNum = sNum.toCharArray(); 9 | int sum = 0; 10 | for (int i = 0; i < cNum.length; i++) { 11 | sum += cNum[i] - '0'; // 문자 값을 정수 형으로 변환하여 더해주기 12 | } 13 | System.out.print(sum); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /자료구조/P1253_좋은수.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedReader; 2 | import java.io.IOException; 3 | import java.io.InputStreamReader; 4 | import java.util.Arrays; 5 | import java.util.StringTokenizer; 6 | public class P1253_좋은수 { 7 | public static void main(String[] args) throws NumberFormatException, IOException { 8 | BufferedReader bf = new BufferedReader(new InputStreamReader(System.in)); 9 | int N = Integer.parseInt(bf.readLine()); 10 | int Result = 0; 11 | long A[] = new long[N]; 12 | StringTokenizer st = new StringTokenizer(bf.readLine()); 13 | for (int i = 0; i < N; i++) { 14 | A[i] = Long.parseLong(st.nextToken()); 15 | } 16 | Arrays.sort(A); 17 | for (int k = 0; k < N; k++) { 18 | long find = A[k]; 19 | int i = 0; 20 | int j = N - 1; 21 | while (i < j) { // 투포인터 알고리즘 22 | if (A[i] + A[j] == find) { 23 | // find는 서로 다른 두 수의 합이여야됨을 체크 24 | if (i != k && j != k) { 25 | Result++; 26 | break; 27 | } else if (i == k) { 28 | i++; 29 | } else if (j == k) { 30 | j--; 31 | } 32 | } else if (A[i] + A[j] < find) { 33 | i++; 34 | } else { 35 | j--; 36 | } 37 | } 38 | } 39 | System.out.println(Result); 40 | bf.close(); 41 | } 42 | } -------------------------------------------------------------------------------- /자료구조/P12891_DNA비밀번호.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedReader; 2 | import java.io.IOException; 3 | import java.io.InputStreamReader; 4 | import java.util.Arrays; 5 | import java.util.StringTokenizer; 6 | 7 | public class P12891_DNA비밀번호 { 8 | static int checkArr[]; 9 | static int myArr[]; 10 | static int checkSecret; 11 | 12 | public static void main(String[] args) throws NumberFormatException, IOException { 13 | BufferedReader bf = new BufferedReader(new InputStreamReader(System.in)); 14 | StringTokenizer st = new StringTokenizer(bf.readLine()); 15 | int S = Integer.parseInt(st.nextToken()); 16 | int P = Integer.parseInt(st.nextToken()); 17 | int Result = 0; 18 | char A[] = new char[S]; 19 | checkArr = new int[4]; 20 | myArr = new int[4]; 21 | checkSecret = 0; 22 | A = bf.readLine().toCharArray(); 23 | st = new StringTokenizer(bf.readLine()); 24 | for (int i = 0; i < 4; i++) { 25 | checkArr[i] = Integer.parseInt(st.nextToken()); 26 | if (checkArr[i] == 0) 27 | checkSecret++; 28 | } 29 | for (int i = 0; i < P; i++) { //초기 P부분 문자열 처리 부분 30 | Add(A[i]); 31 | } 32 | if (checkSecret == 4) 33 | Result++; 34 | // 슬라이딩 윈도우 처리 부분 35 | for (int i = P; i < S; i++) { 36 | int j = i - P; 37 | Add(A[i]); 38 | Remove(A[j]); 39 | if (checkSecret == 4) // 4자리 수에 대한 크기가 모두 충족되었을 때는 유효한 비밀번호 40 | Result++; 41 | } 42 | System.out.println(Result); 43 | bf.close(); 44 | } 45 | 46 | private static void Add(char c) { //새로 들어온 문자를 처리해주는 함수 47 | switch (c) { 48 | case 'A': 49 | myArr[0]++; 50 | if (myArr[0] == checkArr[0]) 51 | checkSecret++; 52 | break; 53 | case 'C': 54 | myArr[1]++; 55 | if (myArr[1] == checkArr[1]) 56 | checkSecret++; 57 | break; 58 | case 'G': 59 | myArr[2]++; 60 | if (myArr[2] == checkArr[2]) 61 | checkSecret++; 62 | break; 63 | case 'T': 64 | myArr[3]++; 65 | if (myArr[3] == checkArr[3]) 66 | checkSecret++; 67 | break; 68 | } 69 | } 70 | 71 | private static void Remove(char c) { //제거되는 문자를 처리해주는 함수 72 | switch (c) { 73 | case 'A': 74 | if (myArr[0] == checkArr[0]) 75 | checkSecret--; 76 | myArr[0]--; 77 | break; 78 | case 'C': 79 | if (myArr[1] == checkArr[1]) 80 | checkSecret--; 81 | myArr[1]--; 82 | break; 83 | case 'G': 84 | if (myArr[2] == checkArr[2]) 85 | checkSecret--; 86 | myArr[2]--; 87 | break; 88 | case 'T': 89 | if (myArr[3] == checkArr[3]) 90 | checkSecret--; 91 | myArr[3]--; 92 | break; 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /자료구조/P1546_평균.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | public class P1546_평균 { 3 | public static void main(String[] args) { 4 | Scanner sc = new Scanner(System.in); 5 | int N = sc.nextInt(); 6 | int A[] = new int[N]; 7 | for (int i = 0; i < N; i++) { 8 | A[i] = sc.nextInt(); 9 | } 10 | long sum = 0; 11 | long max = 0; 12 | for (int i = 0; i < N; i++) { 13 | if (A[i] > max) 14 | max = A[i]; 15 | sum = sum + A[i]; 16 | } 17 | // 각각 계산이 아닌 수식 변환을 통해 총합에 대해 한번만 계산해주면 로직이 간단해 집니다. 18 | System.out.println(sum * 100.0 / max / N); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /자료구조/P17298_오큰수.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | import java.io.*; 3 | public class P17298_오큰수 { 4 | public static void main(String[] args) throws IOException { 5 | BufferedReader bf = new BufferedReader(new InputStreamReader(System.in)); 6 | int n = Integer.parseInt(bf.readLine()); 7 | int[]A = new int[n]; // 수열 배열 생성 8 | int[]ans = new int[n]; // 정답 배열 생성 9 | String[] str = bf.readLine().split(" "); 10 | for (int i = 0; i < n; i++) { 11 | A[i] = Integer.parseInt(str[i]); 12 | } 13 | Stack myStack = new Stack<>(); 14 | myStack.push(0); // 처음에는 항상 스택이 비어있으므로 최초 값을 push하여 초기화 15 | for (int i = 1; i < n; i++) { 16 | //스택 비어있지 않고 현재 수열이 스택 TOP인덱스 가르키는 수열보다 크면 17 | while (!myStack.isEmpty() && A[myStack.peek()] < A[i]) { 18 | ans[myStack.pop()] = A[i]; //정답 배열에 오큰수를 현재 수열로 저장하기 19 | } 20 | myStack.push(i); //신규데이터 push 21 | } 22 | while (!myStack.empty()) { 23 | // 반복문을 다 돌고 나왔는데 스택이 비어있지 않다면 빌 때 까지 24 | ans[myStack.pop()] = -1; 25 | // stack에 쌓인 index에 -1을 넣고 26 | } 27 | BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); 28 | for (int i = 0; i < n; i++) { 29 | bw.write(ans[i] + " "); 30 | // 출력한다 31 | } 32 | bw.write("\n"); 33 | bw.flush(); 34 | } 35 | } 36 | 37 | 38 | -------------------------------------------------------------------------------- /자료구조/P1874_스택수열.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | import java.util.Stack; 3 | public class P1874_스택수열 { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | int N = sc.nextInt(); 7 | int[]A = new int[N]; 8 | for (int i = 0; i < N; i++) { 9 | A[i] = sc.nextInt(); 10 | } 11 | Stack stack = new Stack<>(); 12 | StringBuffer bf = new StringBuffer(); 13 | int num = 1; // 오름차순 수 14 | boolean result = true; 15 | for (int i = 0; i < A.length; i++) { 16 | int su = A[i]; // 현재 수열의 수 17 | if (su >= num) { //현재 수열 값 >= 오름차순 자연수 : 값이 같아 질 때까지 push()수행 18 | while (su >= num) { // push() 19 | stack.push(num++); 20 | bf.append("+\n"); 21 | } 22 | stack.pop(); 23 | bf.append("-\n"); 24 | } 25 | else { //현재 수열 값 < 오름차순 자연수: pop()을 수행하여 수열 원소를 꺼냅니다 26 | int n = stack.pop(); 27 | // 스택의 가장 위의 수가 만들어야 하는 수열의 수 보다 크다면 수열 출력 불가능 28 | if (n > su) { 29 | System.out.println("NO"); 30 | result = false; 31 | break; 32 | } // 33 | else { 34 | bf.append("-\n"); 35 | } 36 | } 37 | } 38 | if (result) System.out.println(bf.toString()); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /자료구조/P1940_주몽.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedReader; 2 | import java.io.IOException; 3 | import java.io.InputStreamReader; 4 | import java.util.Arrays; 5 | import java.util.StringTokenizer; 6 | public class P1940_주몽 { 7 | public static void main(String[] args) throws IOException { 8 | BufferedReader bf = new BufferedReader(new InputStreamReader(System.in)); 9 | int N = Integer.parseInt(bf.readLine()); 10 | int M = Integer.parseInt(bf.readLine()); 11 | int[] A = new int[N]; 12 | StringTokenizer st = new StringTokenizer(bf.readLine()); 13 | for (int i = 0; i < N; i++) { 14 | A[i] = Integer.parseInt(st.nextToken()); 15 | } 16 | Arrays.sort(A); 17 | int count = 0; 18 | int i = 0; 19 | int j = N - 1; 20 | while (i < j) { 21 | if (A[i] + A[j] < M) { 22 | i++; 23 | } else if (A[i] + A[j] > M) { 24 | j--; 25 | } else { 26 | count++; 27 | i++; 28 | j--; 29 | } 30 | } 31 | System.out.println(count); 32 | bf.close(); 33 | } 34 | } -------------------------------------------------------------------------------- /자료구조/P2018_연속된자연수의합.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | public class P2018_연속된자연수의합 { 3 | public static void main(String[] args) { 4 | Scanner sc = new Scanner(System.in); 5 | int N = sc.nextInt(); 6 | int count = 1; 7 | int start_index = 1; 8 | int end_index = 1; 9 | int sum = 1; 10 | while (end_index != N) { 11 | if (sum == N) { //sum == N -> End index++; sum = sum + End index; count++; 12 | count++; 13 | end_index++; 14 | sum = sum + end_index; 15 | } else if (sum > N) { //sum > N -> sum = sum - Start index; Start index++; 16 | sum = sum - start_index; 17 | start_index++; 18 | } else { //sum < N -> End index++; sum = sum + End index; 19 | end_index++; 20 | sum = sum + end_index; 21 | } 22 | } 23 | System.out.println(count); 24 | } 25 | } 26 | 27 | 28 | -------------------------------------------------------------------------------- /자료구조/P2164_카드.java: -------------------------------------------------------------------------------- 1 | import java.util.Queue; 2 | import java.util.LinkedList; 3 | import java.util.Scanner; 4 | public class P2164_카드 { 5 | public static void main(String[] args) { 6 | Scanner sc = new Scanner(System.in); 7 | Queue myQueue = new LinkedList<>(); 8 | int N = sc.nextInt(); 9 | for (int i = 1; i <= N; i++) { // 카드를 큐에 저장하기 10 | myQueue.add(i); 11 | } 12 | while (myQueue.size() > 1) { // 카드가 1장 남을 때까지 13 | myQueue.poll(); // 맨 위의 카드를 버림 14 | myQueue.add(myQueue.poll()); // 맨 위의 카드를 가장 아래 카드 밑으로 이동 15 | } 16 | System.out.println(myQueue.poll()); // 마지막으로 남은 카드 출력 17 | } 18 | } -------------------------------------------------------------------------------- /정렬/P10989_수정렬하기3.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedReader; 2 | import java.io.BufferedWriter; 3 | import java.io.IOException; 4 | import java.io.InputStreamReader; 5 | import java.io.OutputStreamWriter; 6 | public class P10989_수정렬하기3 { 7 | public static int[] A; 8 | public static long result; 9 | public static void main(String[] args) throws IOException { 10 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 11 | BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); 12 | int N = Integer.parseInt(br.readLine()); 13 | A = new int[N]; 14 | for (int i = 0; i < N; i++) { 15 | A[i] = Integer.parseInt(br.readLine()); 16 | } 17 | br.close(); 18 | Radix_Sort(A, 5); 19 | for (int i = 0; i < N; i++) { 20 | bw.write(A[i] + "\n"); 21 | } 22 | bw.flush(); 23 | bw.close(); 24 | } 25 | 26 | public static void Radix_Sort(int[] A, int max_size) { 27 | int[] output = new int[A.length]; 28 | int jarisu = 1; 29 | int count = 0; 30 | while (count != max_size) // 최대 자리수 만큼 반복 31 | { 32 | int[] bucket = new int[10]; 33 | for (int i = 0; i < A.length; i++) { 34 | bucket[(A[i] / jarisu) % 10]++; // 일의 자리 부터 시작 35 | } 36 | for (int i = 1; i < 10; i++) { // 합배열을 이용하여 index 계산 37 | bucket[i] += bucket[i - 1]; 38 | } 39 | for (int i = A.length - 1; i >= 0; i--) { // 현재 자리수 기준으로 정렬하기 40 | output[bucket[(A[i] / jarisu % 10)] - 1] = A[i]; 41 | bucket[(A[i] / jarisu) % 10]--; 42 | } 43 | for (int i = 0; i < A.length; i++) { 44 | A[i] = output[i]; // 다음 자리 수 이동을 위해 현재 자리수 기준 정렬 데이터 저장 45 | } 46 | jarisu = jarisu * 10; // 자리수 증가 47 | count++; 48 | } 49 | }; 50 | } 51 | 52 | 53 | -------------------------------------------------------------------------------- /정렬/P11004_K번째수.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedReader; 2 | import java.io.IOException; 3 | import java.io.InputStreamReader; 4 | import java.util.StringTokenizer; 5 | 6 | public class P11004_K번째수 { 7 | public static void main(String[] args) throws IOException { 8 | BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); 9 | StringTokenizer st = new StringTokenizer(in.readLine()); 10 | int N = Integer.parseInt(st.nextToken()); 11 | int K = Integer.parseInt(st.nextToken()); 12 | st = new StringTokenizer(in.readLine()); 13 | int[] A = new int[N]; 14 | for (int i = 0; i < N; i++) { 15 | A[i] = Integer.parseInt(st.nextToken()); 16 | } 17 | quickSort(A, 0, N - 1, K - 1); 18 | System.out.println(A[K - 1]); 19 | } 20 | public static void quickSort(int[] A, int S, int E, int K) { 21 | if(S pivot){ //K가 pivot보다 크면 왼쪽만 정렬 30 | quickSort(A, pivot+1, E, K); 31 | } 32 | } 33 | } 34 | 35 | private static int partition(int[] A, int S, int E){ 36 | if(S+1==E) { 37 | if(A[S]>A[E])swap(A,S,E); 38 | return E; 39 | } 40 | int M = (S + E) / 2; 41 | swap(A, S, M); // 중앙값을 1번째 요소로 이동하기 42 | int pivot = A[S]; 43 | int i = S+1, j = E; 44 | 45 | while (i <= j) { 46 | while (pivot < A[j] && j > 0 ){ //피벗보다 작은 수가 나올때까지 j-- 47 | j--; 48 | } 49 | while (pivot > A[i] && i tmp[index2]) { 38 | A[k] = tmp[index2]; 39 | k++; 40 | index2++; 41 | } else { 42 | A[k] = tmp[index1]; 43 | k++; 44 | index1++; 45 | } 46 | } 47 | // 한쪽 그룹이 모두 선택된 후 남아있는 값 정리하기 48 | while (index1 <= m) { 49 | A[k] = tmp[index1]; 50 | k++; 51 | index1++; 52 | } 53 | while (index2 <= e) { 54 | A[k] = tmp[index2]; 55 | k++; 56 | index2++; 57 | } 58 | 59 | } 60 | } -------------------------------------------------------------------------------- /정렬/P11399_ATM.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | public class P11399_ATM { 3 | public static void main(String[] args) { 4 | Scanner sc = new Scanner(System.in); 5 | int N = sc.nextInt(); 6 | int[] A = new int[N]; 7 | int[] S = new int[N]; 8 | for (int i = 0; i < N; i++) { 9 | A[i] = sc.nextInt(); 10 | } 11 | for (int i = 1; i < N; i++) { //삽입 정렬 12 | int insert_point = i; 13 | int insert_value = A[i]; 14 | for (int j = i-1; j >= 0; j--) { 15 | if (A[j] < A[i]) 16 | { 17 | insert_point = j+1; 18 | break; 19 | } 20 | if(j==0) { 21 | insert_point = 0; 22 | } 23 | } 24 | for (int j = i; j > insert_point; j--) { 25 | A[j] = A[j-1]; 26 | } 27 | A[insert_point] =insert_value; 28 | } 29 | S[0]=A[0]; //합배열 만들기 30 | for (int i = 1; i < N; i++) { 31 | S[i] = S[i-1]+A[i]; 32 | } 33 | int sum = 0; //합배열 총합 구하기 34 | for (int i = 0; i < N; i++) { 35 | sum = sum + S[i]; 36 | } 37 | System.out.println(sum); 38 | } 39 | } -------------------------------------------------------------------------------- /정렬/P1377_버블소트1.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedReader; 2 | import java.io.IOException; 3 | import java.io.InputStreamReader; 4 | import java.util.Arrays; 5 | public class P1377_버블소트1 { 6 | public static void main(String[] args) throws IOException { 7 | BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); 8 | int N = Integer.parseInt(reader.readLine()); 9 | mData[] A = new mData[N]; 10 | for (int i = 0; i < N; i++) { 11 | A[i] = new mData(Integer.parseInt(reader.readLine()), i); 12 | } 13 | Arrays.sort(A);//A배열 정렬 O(nlogn)시간 복잡도 14 | int Max = 0; 15 | for (int i = 0; i < N; i++) { 16 | if (Max < A[i].index - i) //정렬 전 index - 정렬 후 index 계산 값의 최대 값을 찾아 저장 17 | Max = A[i].index - i; 18 | } 19 | System.out.println(Max + 1); 20 | } 21 | } 22 | 23 | class mData implements Comparable { 24 | int value; 25 | int index; 26 | 27 | public mData(int value, int index) { 28 | super(); 29 | this.value = value; 30 | this.index = index; 31 | } 32 | 33 | @Override 34 | public int compareTo(mData o) {//value 기준 오름차순 정렬 35 | return this.value - o.value; 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /정렬/P1427_내림차순정렬.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | public class P1427_내림차순정렬 { 3 | public static void main(String[] args) { 4 | Scanner sc = new Scanner(System.in); 5 | String str = sc.next(); 6 | int[] A = new int[str.length()]; 7 | for (int i = 0; i < str.length(); i++) { 8 | A[i] = Integer.parseInt(str.substring(i, i + 1)); 9 | } 10 | for (int i = 0; i < str.length(); i++) { 11 | int Max = i; 12 | for (int j = i + 1; j < str.length(); j++) { 13 | if (A[j] > A[Max]) //내림차순이므로 최대 값을 찾음 14 | Max = j; 15 | } 16 | if (A[i] < A[Max]) { 17 | int temp = A[i]; 18 | A[i] = A[Max]; 19 | A[Max] = temp; 20 | } 21 | } 22 | for (int i = 0; i < str.length(); i++) { 23 | System.out.print(A[i]); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /정렬/P1517_버블소트2.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedReader; 2 | import java.io.IOException; 3 | import java.io.InputStreamReader; 4 | import java.util.Arrays; 5 | import java.util.StringTokenizer; 6 | public class P1517_버블소트2 { 7 | public static int[] A, tmp; 8 | public static long result; 9 | public static void main(String[] args) throws IOException { 10 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 11 | int N = Integer.parseInt(br.readLine()); 12 | A = new int[N + 1]; 13 | tmp = new int[N + 1]; 14 | StringTokenizer st = new StringTokenizer(br.readLine()); 15 | for (int i = 1; i <= N; i++) { 16 | A[i] = Integer.parseInt(st.nextToken()); 17 | } 18 | result = 0; 19 | merget_sort(1, N); //병합정렬 수행하기 20 | System.out.println(result); 21 | } 22 | 23 | private static void merget_sort(int s, int e) { 24 | if (e - s < 1) 25 | return; 26 | int m = s + (e - s) / 2; 27 | //재귀함수 형태로 구현 28 | merget_sort(s, m); 29 | merget_sort(m + 1, e); 30 | for (int i = s; i <= e; i++) { 31 | tmp[i] = A[i]; 32 | } 33 | int k = s; 34 | int index1 = s; 35 | int index2 = m + 1; 36 | while (index1 <= m && index2 <= e) { //두 그룹을 Merge 해주는 로직 37 | if (tmp[index1] > tmp[index2]) { 38 | A[k] = tmp[index2]; 39 | result = result + index2 - k; // 뒤쪽 데이터 값이 작아 선택되는 경우 결과 값 업데이트 40 | k++; 41 | index2++; 42 | } else { 43 | A[k] = tmp[index1]; 44 | k++; 45 | index1++; 46 | } 47 | } 48 | while (index1 <= m) { 49 | A[k] = tmp[index1]; 50 | k++; 51 | index1++; 52 | } 53 | while (index2 <= e) { 54 | A[k] = tmp[index2]; 55 | k++; 56 | index2++; 57 | } 58 | 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /정렬/P2750_수정렬하기.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | public class P2750_수정렬하기 { 3 | public static void main(String[] args) { 4 | Scanner sc = new Scanner(System.in); 5 | int N = sc.nextInt(); 6 | int[] A = new int[N]; 7 | for (int i = 0; i < N; i++) { 8 | A[i] = sc.nextInt(); 9 | } 10 | for (int i = 0; i < N - 1; i++) { 11 | for (int j = 0; j < N - 1 - i; j++) { 12 | if (A[j] > A[j + 1]) { 13 | int temp = A[j]; 14 | A[j] = A[j + 1]; 15 | A[j + 1] = temp; 16 | } 17 | } 18 | } 19 | for (int i = 0; i < N; i++) { 20 | System.out.println(A[i]); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /정렬/P2751_수정렬하기2.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedReader; 2 | import java.io.BufferedWriter; 3 | import java.io.IOException; 4 | import java.io.InputStreamReader; 5 | import java.io.OutputStreamWriter; 6 | public class P2751_수정렬하기2 { 7 | public static int[] A, tmp; 8 | public static long result; 9 | public static void main(String[] args) throws IOException { 10 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 11 | BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); 12 | int N = Integer.parseInt(br.readLine()); 13 | A = new int[N + 1]; 14 | tmp = new int[N + 1]; 15 | for (int i = 1; i <= N; i++) { 16 | A[i] = Integer.parseInt(br.readLine()); 17 | } 18 | merget_sort(1, N); // 병합정렬 수행하기 19 | for (int i = 1; i <= N; i++) { 20 | bw.write(A[i] + "\n"); 21 | } 22 | bw.flush(); 23 | bw.close(); 24 | } 25 | 26 | private static void merget_sort(int s, int e) { 27 | if (e - s < 1) 28 | return; 29 | int m = s + (e - s) / 2; 30 | // 재귀함수 형태로 구현 31 | merget_sort(s, m); 32 | merget_sort(m + 1, e); 33 | for (int i = s; i <= e; i++) { 34 | tmp[i] = A[i]; 35 | } 36 | int k = s; 37 | int index1 = s; 38 | int index2 = m + 1; 39 | while (index1 <= m && index2 <= e) { // 두 그룹을 Merge 해주는 로직 40 | if (tmp[index1] > tmp[index2]) { 41 | A[k] = tmp[index2]; 42 | k++; 43 | index2++; 44 | } else { 45 | A[k] = tmp[index1]; 46 | k++; 47 | index1++; 48 | } 49 | } 50 | // 한쪽 그룹이 모두 선택된 후 남아있는 값 정리하기 51 | while (index1 <= m) { 52 | A[k] = tmp[index1]; 53 | k++; 54 | index1++; 55 | } 56 | while (index2 <= e) { 57 | A[k] = tmp[index2]; 58 | k++; 59 | index2++; 60 | } 61 | 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /정수론/P1016_제곱이아닌수.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class P1016_제곱이아닌수 { 3 | public static void main(String[] args) throws Exception { 4 | Scanner sc = new Scanner(System.in); 5 | long Min = sc.nextLong(); 6 | long Max = sc.nextLong(); 7 | boolean[] Check = new boolean[(int) (Max - Min + 1)]; // 최대 최소 차이만큼 배열 선언 8 | // 2의 제곱수인 4부터 max보다 작거나 같은 까지 반복 9 | for (long i = 2; i * i <= Max; i++) { 10 | long pow = i * i; // 제곱수 11 | long start_index = Min / pow; 12 | ; 13 | if (Min % pow != 0) 14 | start_index++; // 나머지가 있으면 1을 더해주어야 Min보다 큰 제곱수 부터 시작됨 15 | for (long j = start_index; pow * j <= Max; j++) { // 제곱수를 true로 변경 16 | Check[(int) ((j * pow) - Min)] = true; 17 | } 18 | } 19 | int count = 0; 20 | for (int i = 0; i <= Max - Min; i++) { 21 | if (!Check[i]) { 22 | count++; 23 | } 24 | } 25 | System.out.println(count); 26 | } 27 | } -------------------------------------------------------------------------------- /정수론/P1033_칵테일.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedWriter; 2 | import java.io.OutputStreamWriter; 3 | import java.util.*; 4 | 5 | public class P1033_칵테일 { 6 | static ArrayList[] A; 7 | static long lcm; 8 | static boolean visited[]; 9 | static long D[]; 10 | public static void main(String[] args) throws Exception { 11 | Scanner sc = new Scanner(System.in); 12 | BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); 13 | int N = sc.nextInt(); 14 | A = new ArrayList[N]; 15 | visited = new boolean[N]; 16 | D = new long[N]; 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | lcm = 1; 25 | for (int i = 0; i < N; i++) { 26 | A[i] = new ArrayList(); 27 | } 28 | for (int i = 0; i < N - 1; i++) { 29 | int a = sc.nextInt(); 30 | int b = sc.nextInt(); 31 | int p = sc.nextInt(); 32 | int q = sc.nextInt(); 33 | A[a].add(new cNode(b, p, q)); 34 | A[b].add(new cNode(a, q, p)); 35 | lcm *= (p * q / gcd(p, q)); // 두 수의 최소 공배수는 두수의 곱을 최대 공약수로 나눈 것입니다. 36 | } 37 | D[0] = lcm; 38 | DFS(0); 39 | long mgcd = D[0]; 40 | for (int i = 1; i < N; i++) { 41 | mgcd = gcd(mgcd, D[i]); 42 | } 43 | for (int i = 0; i < N; i++) { 44 | System.out.print(D[i] / mgcd + " "); 45 | } 46 | } 47 | 48 | public static long gcd(long a, long b) { 49 | if (b == 0) 50 | return a; 51 | else 52 | return gcd(b, a % b); 53 | } 54 | 55 | public static void DFS(int node) { // DFS구현 56 | visited[node] = true; 57 | for (cNode i : A[node]) { 58 | int next = i.getB(); 59 | if (!visited[next]) { 60 | D[next] = D[node] * i.getQ() / i.getP(); //주어진 비율로 다음 노드 값 업데이트 61 | DFS(next); 62 | } 63 | } 64 | } 65 | } 66 | class cNode { 67 | int b; 68 | int p; 69 | int q; 70 | 71 | public cNode(int b, int p, int q) { 72 | super(); 73 | this.b = b; 74 | this.p = p; 75 | this.q = q; 76 | } 77 | public int getB() { 78 | return b; 79 | } 80 | public int getP() { 81 | return p; 82 | } 83 | public int getQ() { 84 | return q; 85 | } 86 | } -------------------------------------------------------------------------------- /정수론/P11689_GCDNK1.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | public class P11689_GCDNK1 { 3 | public static void main(String[] args) throws Exception { 4 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 5 | long n = Long.parseLong(br.readLine()); 6 | long result = n; 7 | for (long p = 2; p <= Math.sqrt(n); p++) { // 제곱근까지만 진행 8 | if (n % p == 0) { // p가 소인수인지 확인 9 | result = result - result / p; // 결과 값 업데이트 10 | while (n % p == 0) { // 해당 소인수를 지워줌 2^7*11이라면 2^7을 없애고 11만 남김 11 | n /= p; 12 | } 13 | } 14 | } 15 | if (n > 1) // 아직 소인수 구성이 남아있는 경우 16 | //(반복문에서 제곱근까지만 탐색했기 때문에 1개의 소인수가 누락되는 케이스) 17 | result = result - result / n; 18 | System.out.println(result); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /정수론/P1456_거의소수.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | public class P1456_거의소수 { 3 | public static void main(String[] args) { 4 | Scanner sc = new Scanner(System.in); 5 | long Min = sc.nextLong(); 6 | long Max = sc.nextLong(); 7 | long[] A = new long[10000001]; 8 | for (int i = 2; i < A.length; i++) { 9 | A[i] = i; 10 | } 11 | for (int i = 2; i <= Math.sqrt(A.length); i++) { // 제곱근 까지만 수행 12 | if (A[i] == 0) { 13 | continue; 14 | } 15 | for (int j = i + i; j < A.length; j = j + i) { // 배수 지우기 16 | A[j] = 0; 17 | } 18 | } 19 | int count = 0; 20 | for (int i = 2; i < 10000001; i++) { 21 | if (A[i] != 0) { 22 | long temp = A[i]; 23 | while ((double)A[i] <= (double)Max/(double)temp) { 24 | if ((double)A[i] >= (double)Min/(double)temp ) { 25 | count++; 26 | } 27 | temp = temp * A[i]; 28 | } 29 | } 30 | } 31 | System.out.println(count); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /정수론/P1747_소수팰린드롬.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | public class P1747_소수팰린드롬 { 3 | public static void main(String[] args) { 4 | Scanner sc = new Scanner(System.in); 5 | int N = sc.nextInt(); 6 | int[] A = new int[10000001]; // N의 범위까지 소수 구해주기 7 | for (int i = 2; i < A.length; i++) { 8 | A[i] = i; 9 | } 10 | for (int i = 2; i < Math.sqrt(A.length); i++) { // 제곱근 까지만 수행 11 | if (A[i] == 0) { 12 | continue; 13 | } 14 | for (int j = i + i; j < A.length; j = j + i) { // 배수 지우기 15 | A[j] = 0; 16 | } 17 | } 18 | int i = N; 19 | while (true) { // N부터 1씩 증가시켜가면서 소수와 펠린드롬 수가 맞는지 확인 20 | if (A[i] != 0) { 21 | int result = A[i]; 22 | if (isPalindrome(result)) { 23 | System.out.println(result); 24 | break; 25 | } 26 | } 27 | i++; 28 | } 29 | } 30 | private static boolean isPalindrome(int target) // 펠린드롬수 판별 함수 31 | { 32 | char temp[] = String.valueOf(target).toCharArray(); 33 | int s = 0; 34 | int e = temp.length - 1; 35 | while (s < e) { 36 | if (temp[s] != temp[e]) 37 | return false; 38 | s++; 39 | e--; 40 | } 41 | return true; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /정수론/P1850_최대공약수.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedWriter; 2 | import java.io.OutputStreamWriter; 3 | import java.util.*; 4 | public class P1850_최대공약수 { 5 | public static void main(String[] args) throws Exception { 6 | Scanner sc = new Scanner(System.in); 7 | BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); 8 | long a = sc.nextLong(); 9 | long b = sc.nextLong(); 10 | long result = gcd(a, b); 11 | while (result > 0) { 12 | bw.write("1"); 13 | result--; 14 | } 15 | bw.flush(); 16 | bw.close(); 17 | } 18 | public static long gcd(long a, long b) { 19 | if (b == 0) 20 | return a; 21 | else 22 | return gcd(b, a % b); 23 | } 24 | } -------------------------------------------------------------------------------- /정수론/P1929_소수구하기.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | public class P1929_소수구하기 { 3 | public static void main(String[] args) { 4 | Scanner in = new Scanner(System.in); 5 | int M = in.nextInt(); 6 | int N = in.nextInt(); 7 | int[] A = new int[N + 1]; 8 | for (int i = 2; i <= N; i++) { 9 | A[i] = i; 10 | } 11 | for (int i = 2; i <= Math.sqrt(N); i++) { // 제곱근 까지만 수행 12 | if (A[i] == 0) { 13 | continue; 14 | } 15 | for (int j = i + i; j <= N; j = j + i) { // 배수 지우기 16 | A[j] = 0; 17 | } 18 | } 19 | for (int i = M; i <= N; i++) { 20 | if (A[i] != 0) { 21 | System.out.println(A[(int) i]); 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /정수론/P1934_최소공배수.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class P1934_최소공배수 { 3 | public static void main(String[] args) throws Exception { 4 | Scanner sc = new Scanner(System.in); 5 | int t = sc.nextInt(); 6 | for (int i = 0; i < t; i++) { 7 | int a = sc.nextInt(); 8 | int b = sc.nextInt(); 9 | int result = a * b / gcd(a, b); 10 | System.out.println(result); 11 | } 12 | } 13 | public static int gcd(int a, int b) { 14 | if (b == 0) 15 | return a; 16 | else 17 | return gcd(b, a % b); 18 | } 19 | } -------------------------------------------------------------------------------- /정수론/P21568_AxByC.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedReader; 2 | import java.io.BufferedWriter; 3 | import java.io.InputStreamReader; 4 | import java.io.OutputStreamWriter; 5 | import java.util.StringTokenizer; 6 | public class P21568_AxByC { 7 | public static void main(String[] args) throws Exception{ 8 | BufferedReader br = new BufferedReader( new InputStreamReader(System.in)); 9 | BufferedWriter bw = new BufferedWriter( new OutputStreamWriter(System.out)); 10 | StringTokenizer st = new StringTokenizer(br.readLine()); 11 | int a = Integer.parseInt(st.nextToken()); 12 | int b = Integer.parseInt(st.nextToken()); 13 | int c = Integer.parseInt(st.nextToken()); 14 | long gcd = gcd(a,b); 15 | if(c%gcd != 0) { 16 | System.out.println(-1); 17 | }else { 18 | int mok = (int) (c/gcd); 19 | long[] ret = Excute(a, b); 20 | System.out.println(ret[0]*mok + " " + ret[1]*mok); 21 | } 22 | } 23 | private static long[] Excute(long a, long b) { 24 | long[] ret = new long[2]; 25 | if(b==0) { 26 | ret[0] = 1; 27 | ret[1] = 0; 28 | return ret; 29 | } 30 | long q = a/b; 31 | long[] v = Excute(b, a%b); //재귀 형태로 호제 법 수행 32 | ret[0] = v[1]; //역으로 올라오면서 X Y값을 계산해주는 로직 33 | ret[1] = v[0] - v[1]*q; 34 | return ret; 35 | } 36 | private static long gcd(long a, long b) { 37 | while(b!= 0) { 38 | long temp = a%b; 39 | a=b; 40 | b=temp; 41 | } 42 | return Math.abs(a); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /조합/P1010_다리놓기.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | public class P1010_다리놓기 { 3 | static long[][] D; 4 | public static void main(String[] args) { 5 | D = new long[31][31]; 6 | for (int i = 0; i <= 30; i++) { 7 | D[i][1] = i; 8 | D[i][0] = 1; 9 | D[i][i] = 1; 10 | } 11 | for (int i = 2; i <= 30; i++) { 12 | for (int j = 1; j < i; j++) { 13 | D[i][j] = D[i - 1][j] + D[i - 1][j - 1]; 14 | } 15 | } 16 | Scanner sc = new Scanner(System.in); 17 | int t = sc.nextInt(); 18 | for (int i = 0; i < t; i++) { 19 | int N = sc.nextInt(); 20 | int M = sc.nextInt(); 21 | System.out.println(D[M][N]); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /조합/P11050_이항계수.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class P11050_이항계수 { 3 | static int N, K; 4 | static int[][] D; 5 | public static void main(String[] args) throws Exception { 6 | Scanner sc = new Scanner(System.in); 7 | N = sc.nextInt(); 8 | K = sc.nextInt(); 9 | D = new int[N + 1][N + 1]; 10 | for (int i = 0; i <= N; i++) { 11 | D[i][1] = i; 12 | D[i][0] = 1; 13 | D[i][i] = 1; 14 | } 15 | for (int i = 2; i <= N; i++) { 16 | for (int j = 1; j < i; j++) { 17 | D[i][j] = D[i - 1][j] + D[i - 1][j - 1]; 18 | } 19 | } 20 | System.out.println(D[N][K]); 21 | } 22 | } -------------------------------------------------------------------------------- /조합/P11051_이항계수2.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class P11051_이항계수2 { 3 | static int N, K; 4 | static int[][] D; 5 | public static void main(String[] args) throws Exception { 6 | Scanner sc = new Scanner(System.in); 7 | N = sc.nextInt(); 8 | K = sc.nextInt(); 9 | D = new int[N + 1][N + 1]; 10 | for (int i = 0; i <= N; i++) { 11 | D[i][1] = i; 12 | D[i][0] = 1; 13 | D[i][i] = 1; 14 | } 15 | for (int i = 2; i <= N; i++) { 16 | for (int j = 1; j < i; j++) { 17 | D[i][j] = D[i - 1][j] + D[i - 1][j - 1]; 18 | D[i][j] = D[i][j]%10007; 19 | } 20 | } 21 | System.out.println(D[N][K]); 22 | } 23 | } -------------------------------------------------------------------------------- /조합/P1256_사전.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class P1256_사전 { 3 | static int N, M, K; 4 | static int[][] D; 5 | public static void main(String[] args) throws Exception { 6 | Scanner sc = new Scanner(System.in); 7 | N = sc.nextInt(); 8 | M = sc.nextInt(); 9 | K = sc.nextInt(); 10 | D = new int[202][202]; 11 | for (int i = 0; i <= 200; i++) { // 조합 테이블 초기화 12 | for (int j = 0; j <= i; j++) { 13 | if (j == 0 || j == i) 14 | D[i][j] = 1; 15 | else { 16 | D[i][j] = D[i - 1][j - 1] + D[i - 1][j]; 17 | if (D[i][j] > 1000000000) D[i][j] = 1000000001; // K 범위가 넘어가면 범위 최대 값 저장 18 | } 19 | } 20 | } 21 | if (D[N + M][M] < K) // 주어진 자리수로 만들 수 없는 K번째 수이면 22 | System.out.println("-1"); 23 | else { 24 | while (!(N == 0 && M == 0)) { 25 | // a를 선택하였을때 남은 문자로 만들 수 있는 모든 경우의 수가 K보다 크면 26 | if (D[N - 1 + M][M] >= K) { 27 | System.out.print("a"); 28 | N--; 29 | } else { // 모든 경우의 수가 K보다 작으면 30 | System.out.print("z"); 31 | K = K - D[N - 1 + M][M]; //K값 업데이트 32 | M--; 33 | } 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /조합/P13251_조약돌꺼내기.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedReader; 2 | import java.io.IOException; 3 | import java.io.InputStreamReader; 4 | import java.util.StringTokenizer; 5 | public class P13251_조약돌꺼내기 { 6 | public static void main(String[] args) throws IOException { 7 | int M, K, T; 8 | int D[] = new int[51]; 9 | double probability[] = new double[51]; 10 | double ans; 11 | T = 0; 12 | BufferedReader bf = new BufferedReader(new InputStreamReader(System.in)); 13 | StringTokenizer st = new StringTokenizer(bf.readLine()); 14 | M = Integer.parseInt(st.nextToken()); 15 | st = new StringTokenizer(bf.readLine()); 16 | for (int i = 0; i < M; i++) { 17 | D[i] = Integer.parseInt(st.nextToken()); 18 | T += D[i]; 19 | } 20 | st = new StringTokenizer(bf.readLine()); 21 | K = Integer.parseInt(st.nextToken()); 22 | ans = 0.0; 23 | for (int i = 0; i < M; i++) { 24 | if (D[i] >= K) { 25 | probability[i] = 1.0; 26 | for (int k = 0; k < K; k++) 27 | probability[i] *= (double) (D[i] - k) / (T - k); 28 | } 29 | ans += probability[i]; 30 | } 31 | System.out.println(ans); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /조합/P1722_순열의순서.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedReader; 2 | import java.io.IOException; 3 | import java.io.InputStreamReader; 4 | import java.util.StringTokenizer; 5 | 6 | public class P1722_순열의순서 { 7 | public static void main(String[] args) throws IOException { 8 | int N, Q; 9 | long F[] = new long[21]; 10 | int S[] = new int[21]; 11 | boolean visit[] = new boolean[21]; 12 | BufferedReader bf = new BufferedReader(new InputStreamReader(System.in)); 13 | StringTokenizer st = new StringTokenizer(bf.readLine()); 14 | N = Integer.parseInt(st.nextToken()); 15 | st = new StringTokenizer(bf.readLine()); 16 | Q = Integer.parseInt(st.nextToken()); 17 | F[0] = 1; 18 | for (int i = 1; i <= N; i++) { // 팩토리얼 초기화 -> 각 자리수에서 만들수 있는 경우의 수 19 | F[i] = F[i - 1] * i; 20 | } 21 | if (Q == 1) { 22 | long K = Long.parseLong(st.nextToken()); 23 | for (int i = 1; i <= N; i++) { 24 | for (int j = 1, cnt = 1; j <= N; j++) { 25 | if (visit[j]) 26 | continue; // 이미 사용한 숫자는 사용할 수 없음 27 | if (K <= cnt * F[N - i]) { // 주어진 K에 따라 각 자리에 들어갈 수 있는 수 찾기 28 | K -= ((cnt - 1) * F[N - i]); 29 | S[i] = j; 30 | visit[j] = true; 31 | break; 32 | } 33 | cnt++; 34 | } 35 | } 36 | for (int i = 1; i <= N; i++) { 37 | System.out.print(S[i] + " "); 38 | } 39 | } else { 40 | long K = 1; 41 | for (int i = 1; i <= N; i++) { 42 | S[i] = Integer.parseInt(st.nextToken()); 43 | long cnt = 0; 44 | for (int j = 1; j < S[i]; j++) { 45 | if (visit[j] == false) { 46 | cnt++; // 미사용 숫자 개수만큼 카운트 47 | } 48 | } 49 | K += cnt * F[N - i]; // 자리수 개수에 따라 순서 더해주기 50 | visit[S[i]] = true; 51 | } 52 | System.out.println(K); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /조합/P1947_선물전달.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | public class P1947_선물전달 { 3 | public static void main(String[] args) { 4 | Scanner sc = new Scanner(System.in); 5 | int N = sc.nextInt(); 6 | long mod = 1000000000; 7 | long D[] = new long[1000001]; 8 | D[1] = 0; 9 | D[2] = 1; 10 | for(int i=3; i<=N; i++){ 11 | D[i] = (i-1)*(D[i-1]+D[i-2])%mod; 12 | } 13 | System.out.println(D[N]); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /조합/P2775_부녀회장이될테야.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class P2775_부녀회장이될테야 { 3 | static int T, N, K; 4 | static int[][] D; 5 | public static void main(String[] args) throws Exception { 6 | D = new int[15][15]; 7 | for (int i = 0; i < 15; i++) { //초기화 8 | D[i][1] = 1; 9 | D[0][i] = i; 10 | } 11 | for (int i = 1; i < 15; i++) { 12 | for (int j = 2; j < 15; j++) { 13 | D[i][j] = D[i][j-1] + D[i-1][j]; // 점화식 14 | } 15 | } 16 | Scanner sc = new Scanner(System.in); 17 | T = sc.nextInt(); 18 | for(int i=0; i[] A; 6 | public static void main(String[] args) { 7 | Scanner sc = new Scanner(System.in); 8 | int N = sc.nextInt(); // 정점의 수 9 | A = new ArrayList[N + 1]; 10 | for (int i = 1; i <= N; i++) { 11 | A[i] = new ArrayList(); 12 | } 13 | for (int i = 0; i < N; i++) { 14 | int S = sc.nextInt(); 15 | while(true) 16 | { 17 | int E = sc.nextInt(); 18 | if(E==-1)break; 19 | int V = sc.nextInt(); 20 | A[S].add(new Edge_1677(E, V)); 21 | } 22 | } 23 | distance = new int[N+1]; 24 | visited = new boolean[N+1]; 25 | BFS(1); 26 | int Max = 1; 27 | for(int i=2; i<=N; i++) { 28 | if(distance[Max] queue = new LinkedList(); 40 | queue.add(index); 41 | visited[index] = true; 42 | while (!queue.isEmpty()) { 43 | int now_node = queue.poll(); 44 | for (Edge_1677 i : A[now_node]) { 45 | int e = i.e; 46 | int v = i.value; 47 | if (!visited[e]) { 48 | visited[e] = true; 49 | queue.add(e); 50 | distance[e]=distance[now_node]+v; 51 | } 52 | } 53 | } 54 | } 55 | } 56 | class Edge_1677 { 57 | int e; 58 | int value; 59 | 60 | public Edge_1677(int e, int value) { 61 | this.e = e ; 62 | this.value = value; 63 | } 64 | } 65 | 66 | -------------------------------------------------------------------------------- /탐색/P11724_연결요소의개수.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.util.*; 3 | public class P11724_연결요소의개수 { 4 | static ArrayList[] A; 5 | static boolean visited[]; 6 | public static void main(String[] args) throws IOException { 7 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 8 | StringTokenizer st = new StringTokenizer(br.readLine()); 9 | int n = Integer.parseInt(st.nextToken()); 10 | int m = Integer.parseInt(st.nextToken()); 11 | A = new ArrayList[n + 1]; 12 | visited = new boolean[n + 1]; 13 | for (int i = 1; i < n + 1; i++) { // 인접 리스트 초기화 14 | A[i] = new ArrayList(); 15 | } 16 | for (int i = 0; i < m; i++) { 17 | st = new StringTokenizer(br.readLine()); 18 | int s = Integer.parseInt(st.nextToken()); 19 | int e = Integer.parseInt(st.nextToken()); 20 | A[s].add(e); // 양 방향 간선이므로 양쪽으로 간선을 더 해준다 21 | A[e].add(s); 22 | } 23 | int count = 0; 24 | for (int i = 1; i < n + 1; i++) { 25 | if (!visited[i]) { // 미 방문한 정점이 없을 때까지 반복 26 | count++; 27 | DFS(i); 28 | } 29 | } 30 | System.out.println(count); 31 | } 32 | static void DFS(int v) { 33 | if (visited[v]) { 34 | return; 35 | } 36 | visited[v] = true; 37 | for (int i : A[v]) { 38 | if (visited[i] == false) { // 연결 정점 중 방문하지 않았던 정점만 탐색함 39 | DFS(i); 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /탐색/P1206_DFS와BFS.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class P1206_DFS와BFS { 3 | static boolean visited[]; 4 | static ArrayList[] A; 5 | public static void main(String[] args) { 6 | Scanner scan = new Scanner(System.in); 7 | int N = scan.nextInt(); // 정점의 수 8 | int M = scan.nextInt(); // 간선의 수 9 | int Start = scan.nextInt(); // 시작점 10 | A = new ArrayList[N + 1]; 11 | for (int i = 1; i <= N; i++) { 12 | A[i] = new ArrayList(); 13 | } 14 | for (int i = 0; i < M; i++) { 15 | int S = scan.nextInt(); 16 | int E = scan.nextInt(); 17 | A[S].add(E); 18 | A[E].add(S); 19 | } 20 | // 방문할 수 있는 정점이 여러 개인 경우에는 번호가 작은 것을 먼저 방문 하기 위해 정렬 21 | for (int i = 1; i <= N; i++) { 22 | Collections.sort(A[i]); 23 | } 24 | visited = new boolean[N + 1]; //방문 배열 초기화 25 | DFS(Start); 26 | System.out.println(); 27 | visited = new boolean[N + 1]; //방문 배열 초기화 28 | BFS(Start); 29 | System.out.println(); 30 | 31 | } 32 | 33 | public static void DFS(int node) { // DFS구현 34 | System.out.print(node + " "); 35 | visited[node] = true; 36 | for (int i : A[node]) { 37 | if (!visited[i]) { 38 | DFS(i); 39 | } 40 | } 41 | } 42 | 43 | private static void BFS(int node) { // BFS구현 44 | Queue queue = new LinkedList(); 45 | queue.add(node); 46 | visited[node] = true; 47 | 48 | while (!queue.isEmpty()) { 49 | int now_node = queue.poll(); 50 | System.out.print(now_node + " "); 51 | for (int i : A[now_node]) { 52 | if (!visited[i]) { 53 | visited[i] = true; 54 | queue.add(i); 55 | } 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /탐색/P1300_K번째수.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | public class P1300_K번째수 { 3 | public static void main(String[] args) throws Exception { 4 | Scanner sc = new Scanner(System.in); 5 | int N = sc.nextInt(); 6 | int K = sc.nextInt(); 7 | long start = 1, end = K; 8 | long ans = 0; 9 | // 이분 탐색 수행 10 | while (start <= end) { 11 | long middle = (start + end) / 2; 12 | long cnt = 0; 13 | // 중간 값보다 작은 수는 몇 개인지 계산. 14 | for (int i = 1; i <= N; i++) { 15 | cnt += Math.min(middle / i, N); // 작은 수를 카운트하는 핵심로직 16 | } 17 | if (cnt < K) { 18 | start = middle + 1; 19 | } else { 20 | ans = middle; // 현재 단계의 중간 값을 정답 변수에 저장 21 | end = middle - 1; 22 | } 23 | } 24 | System.out.println(ans); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /탐색/P13023_친구관계파악하기.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class P13023_친구관계파악하기 { 3 | static boolean visited[]; 4 | static ArrayList[] A; 5 | static boolean arrive; 6 | public static void main(String[] args) { 7 | int N; // 정점의 수 8 | int M; // 간선의 수 9 | arrive = false; 10 | Scanner scan = new Scanner(System.in); 11 | N = scan.nextInt(); 12 | M = scan.nextInt(); 13 | A = new ArrayList[N]; 14 | visited = new boolean[N]; 15 | for (int i = 0; i < N; i++) { 16 | A[i] = new ArrayList(); 17 | } 18 | for (int i = 0; i < M; i++) { 19 | int S = scan.nextInt(); 20 | int E = scan.nextInt(); 21 | A[S].add(E); 22 | A[E].add(S); 23 | } 24 | for (int i = 0; i < N; i++) { 25 | DFS(i, 1); 26 | if (arrive) 27 | break; 28 | } 29 | if (arrive) 30 | System.out.println("1"); 31 | else 32 | System.out.println("0"); // 5의 깊이가 없다면 0 출력 33 | } 34 | public static void DFS(int now, int depth) { // DFS구현 35 | if (depth == 5 || arrive) { // 깊이가 5가되면 프로그램 종료 36 | arrive = true; 37 | return; 38 | } 39 | visited[now] = true; 40 | for (int i : A[now]) { 41 | if (!visited[i]) { 42 | DFS(i, depth + 1); 43 | } 44 | } 45 | visited[now] = false; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /탐색/P1920_원하는정수찾기.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | import java.util.Scanner; 3 | public class P1920_원하는정수찾기 { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | int N = sc.nextInt(); 7 | int[] A = new int[N]; 8 | for (int i = 0; i < N; i++) { 9 | A[i] = sc.nextInt(); 10 | } 11 | Arrays.sort(A); 12 | int M = sc.nextInt(); 13 | for (int i = 0; i < M; i++) { 14 | boolean find = false; 15 | int target = sc.nextInt(); 16 | // 이진 탐색 시작 17 | int start = 0; 18 | int end = A.length - 1; 19 | while (start <= end) { 20 | int midi = (start + end) / 2; 21 | int midV = A[midi]; 22 | if (midV > target) { 23 | end = midi - 1; 24 | } else if (midV < target) { 25 | start = midi + 1; 26 | } else { 27 | find = true; 28 | break; 29 | } 30 | } 31 | if (find) { 32 | System.out.println(1); 33 | } else { 34 | System.out.println(0); 35 | } 36 | } 37 | } 38 | } 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /탐색/P2023_신기한소수.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class P2023_신기한소수 { 3 | static int N; 4 | public static void main(String[] args) { 5 | Scanner in = new Scanner(System.in); 6 | N = in.nextInt(); 7 | // 일의 자리 소수는 2 3 5 7 이므로 4개 수에서만 시작 8 | DFS(2, 1); 9 | DFS(3, 1); 10 | DFS(5, 1); 11 | DFS(7, 1); 12 | } 13 | static void DFS(int number, int jarisu) { 14 | if (jarisu == N) { 15 | if (isPrime(number)) { 16 | System.out.println(number); 17 | } 18 | return; 19 | } 20 | for (int i = 1; i < 10; i++) { 21 | if (i % 2 == 0) { // 짝수이면 더 이상 탐색할 필요가 없음 22 | continue; 23 | } 24 | if (isPrime(number * 10 + i)) { // 소수이면 재귀로 자리수를 늘려갑니다. 25 | DFS(number * 10 + i, jarisu + 1); 26 | } 27 | } 28 | } 29 | static boolean isPrime(int num) { 30 | for (int i = 2; i <= num / 2; i++) 31 | if (num % i == 0) 32 | return false; 33 | return true; 34 | } 35 | } -------------------------------------------------------------------------------- /탐색/P2178_미로탐색.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedReader; 2 | import java.io.IOException; 3 | import java.io.InputStreamReader; 4 | import java.util.LinkedList; 5 | import java.util.Queue; 6 | import java.util.StringTokenizer; 7 | public class P2178_미로탐색 { 8 | // 상 우 하 좌 탐색을 위한 배열 선언 9 | static int[] dx = { 0, 1, 0, -1 }; 10 | static int[] dy = { 1, 0, -1, 0 }; 11 | static boolean[][] visited; 12 | static int[][] A; 13 | static int N, M; 14 | public static void main(String args[]) throws IOException { 15 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 16 | StringTokenizer st = new StringTokenizer(br.readLine()); 17 | N = Integer.parseInt(st.nextToken()); 18 | M = Integer.parseInt(st.nextToken()); 19 | A = new int[N][M]; 20 | visited = new boolean[N][M]; 21 | for (int i = 0; i < N; i++) { 22 | st = new StringTokenizer(br.readLine()); 23 | String line = st.nextToken(); 24 | for (int j = 0; j < M; j++) { 25 | A[i][j] = Integer.parseInt(line.substring(j, j + 1)); 26 | } 27 | } 28 | BFS(0, 0); 29 | System.out.println(A[N - 1][M - 1]); 30 | } 31 | 32 | public static void BFS(int i, int j) { 33 | Queue queue = new LinkedList<>(); 34 | queue.offer(new int[] { i, j }); 35 | while (!queue.isEmpty()) { 36 | int now[] = queue.poll(); 37 | visited[i][j] = true; 38 | for (int k = 0; k < 4; k++) { 39 | int x = now[0] + dx[k]; 40 | int y = now[1] + dy[k]; 41 | if (x >= 0 && y >= 0 && x < N && y < M) { // 좌표 유효성 검사 42 | if (A[x][y] != 0 && !visited[x][y]) { // 미방문 정점 검사 43 | visited[x][y] = true; 44 | A[x][y] = A[now[0]][now[1]] + 1; // depth update 45 | queue.add(new int[] { x, y }); 46 | } 47 | } 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /탐색/P2343_블루레이.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | public class P2343_블루레이 { 3 | public static void main(String[] args) { 4 | Scanner sc = new Scanner(System.in); 5 | int N = sc.nextInt(); 6 | int M = sc.nextInt(); 7 | int[] A = new int[N]; 8 | int start = 0; 9 | int end = 0; 10 | for (int i = 0; i < N; i++) { 11 | A[i] = sc.nextInt(); 12 | if (start < A[i]) 13 | start = A[i]; // 레슨 최대값을 시작인덱스로 저장 14 | end = end + A[i]; // 모든 레슨의 총 합을 종료 인덱스로 저장 15 | } 16 | while (start <= end) { 17 | int middle = (start + end) / 2; 18 | int sum = 0; 19 | int count = 0; 20 | for (int i = 0; i < N; i++) { // middle값으로 모든 레슨을 저장 할 수 있는지 확인 21 | if (sum + A[i] > middle) { 22 | count++; 23 | sum = 0; 24 | } 25 | sum = sum + A[i]; 26 | } 27 | if (sum != 0) 28 | count++; 29 | if (count > M) 30 | start = middle + 1; 31 | else 32 | end = middle - 1; 33 | } 34 | System.out.println(start); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /트리/P1068_리프노드.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class P1068_리프노드 { 3 | static ArrayList[] tree; 4 | static boolean[] visit; 5 | static int answer = 0; 6 | static int deleteNode=0; 7 | public static void main(String[] args) { 8 | Scanner sc = new Scanner(System.in); 9 | int N = sc.nextInt(); 10 | tree = new ArrayList[N]; 11 | visit = new boolean[N]; 12 | int root = 0; 13 | for (int i = 0; i < N; i++) { 14 | tree[i] = new ArrayList(); 15 | } 16 | for (int i = 0; i < N; i++) { 17 | int p = sc.nextInt(); 18 | if (p != -1) { 19 | tree[i].add(p); 20 | tree[p].add(i); 21 | } else 22 | root = i; 23 | } 24 | deleteNode = sc.nextInt(); 25 | if (deleteNode == root) 26 | System.out.println(0); 27 | else { 28 | DFS(root); 29 | System.out.println(answer); 30 | } 31 | } 32 | static void DFS(int number) { 33 | visit[number] = true; 34 | int cNode = 0; 35 | for (int i : tree[number]) { 36 | if (visit[i] == false && i != deleteNode) { 37 | cNode++; 38 | DFS(i); 39 | } 40 | } 41 | if (cNode == 0) { 42 | answer++; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /트리/P10868_최솟값.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.util.*; 3 | public class P10868_최솟값 { 4 | static long[] tree; 5 | public static void main(String[] args) throws IOException { 6 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 7 | StringTokenizer st = new StringTokenizer(br.readLine()); 8 | int N = Integer.parseInt(st.nextToken()); // 수의 개수 9 | int M = Integer.parseInt(st.nextToken()); // 구간의 최솟값을 구하는 횟수 10 | int treeHeight = 0; 11 | int lenght = N; 12 | while (lenght != 0) { 13 | lenght /= 2; 14 | treeHeight++; 15 | } 16 | int treeSize = (int) Math.pow(2, treeHeight + 1); 17 | int leftNodeStartIndex = treeSize / 2 - 1; 18 | // 트리 초기화 하기 19 | tree = new long[treeSize + 1]; 20 | for (int i = 0; i < tree.length; i++) { 21 | tree[i] = Integer.MAX_VALUE; 22 | } 23 | // 데이터 입력 받기 24 | for (int i = leftNodeStartIndex + 1; i <= leftNodeStartIndex + N; i++) { 25 | tree[i] = Long.parseLong(br.readLine()); 26 | } 27 | // tree 만들기 28 | setTree(treeSize - 1); 29 | for (int i = 0; i < M; i++) { 30 | st = new StringTokenizer(br.readLine()); 31 | int s = Integer.parseInt(st.nextToken()); 32 | int e = Integer.parseInt(st.nextToken()); 33 | s = s + leftNodeStartIndex; 34 | e = e + leftNodeStartIndex; 35 | System.out.println(getMin(s, e)); 36 | } 37 | br.close(); 38 | } 39 | 40 | private static long getMin(int s, int e) { //범위의 최솟값을 구하는 함수 41 | long Min = Long.MAX_VALUE; 42 | while (s <= e) { 43 | if (s % 2 == 1) { 44 | Min = Math.min(Min, tree[s]); 45 | s++; 46 | } 47 | s = s / 2; 48 | if (e % 2 == 0) { 49 | Min = Math.min(Min, tree[e]); 50 | e--; 51 | } 52 | e = e / 2; 53 | } 54 | return Min; 55 | } 56 | 57 | private static void setTree(int i) { //초기 트리 생성 함수 구현 58 | while (i != 1) { 59 | if (tree[i / 2] > tree[i]) 60 | tree[i / 2] = tree[i]; 61 | i--; 62 | } 63 | 64 | } 65 | } -------------------------------------------------------------------------------- /트리/P11437_LCA.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class P11437_LCA { 3 | static ArrayList[] tree; 4 | static int[] depth; 5 | static int[] parent; 6 | static boolean[] visited; 7 | public static void main(String[] args) { 8 | Scanner sc = new Scanner(System.in); 9 | int N = sc.nextInt(); // 정점의 수 10 | tree = new ArrayList[N + 1]; 11 | for (int i = 1; i <= N; i++) { 12 | tree[i] = new ArrayList(); 13 | } 14 | for (int i = 0; i < N - 1; i++) { // A인접리스트에 그래프 데이터 저장 15 | int s = sc.nextInt(); 16 | int e = sc.nextInt(); 17 | tree[s].add(e); 18 | tree[e].add(s); 19 | } 20 | depth = new int[N + 1]; 21 | parent = new int[N + 1]; 22 | visited = new boolean[N + 1]; 23 | BFS(1); // depth를 BFS를 통하여 구하기 24 | int M = sc.nextInt(); // 질의의 수 25 | for (int i = 0; i < M; i++) { 26 | // 공통 조상을 구할 두 노드 27 | int a = sc.nextInt(); 28 | int b = sc.nextInt(); 29 | int LCA = excuteLCA(a, b); 30 | System.out.println(LCA); 31 | } 32 | } 33 | static int excuteLCA(int a, int b) { 34 | if (depth[a] < depth[b]) { 35 | int temp = a; 36 | a = b; 37 | b = temp; 38 | } 39 | while (depth[a] != depth[b]) { // 두 노드의 Depth 맞춰주기 40 | a = parent[a]; 41 | } 42 | while (a != b) { // 같은 조상이 나올 때까지 한칸씩 올려주기 43 | a = parent[a]; 44 | b = parent[b]; 45 | } 46 | return a; 47 | } 48 | // BFS구현 49 | private static void BFS(int node) { 50 | Queue queue = new LinkedList(); 51 | queue.add(node); 52 | visited[node] = true; 53 | int level = 1; 54 | int now_size = 1; 55 | int count = 0; 56 | while (!queue.isEmpty()) { 57 | int now_node = queue.poll(); 58 | for (int next : tree[now_node]) { 59 | if (!visited[next]) { 60 | visited[next] = true; 61 | queue.add(next); 62 | parent[next] = now_node; //부모 노드 저장 63 | depth[next] = level; //노드 depth 저장 64 | } 65 | } 66 | count++; 67 | if (count == now_size) { 68 | count = 0; 69 | now_size = queue.size(); 70 | level++; 71 | } 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /트리/P11438_LCA2.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedReader; 2 | import java.io.IOException; 3 | import java.io.InputStreamReader; 4 | import java.util.*; 5 | public class P11438_LCA2 { 6 | static ArrayList[] tree; 7 | static int[] depth; 8 | static int kmax; 9 | static int[][] parent; 10 | static boolean[] visited; 11 | public static void main(String[] args) throws NumberFormatException, IOException { 12 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 13 | int N = Integer.parseInt(br.readLine()); // 정점의 수 14 | tree = new ArrayList[N + 1]; 15 | for (int i = 1; i <= N; i++) { 16 | tree[i] = new ArrayList(); 17 | } 18 | for (int i = 0; i < N - 1; i++) { // A인접리스트에 그래프 데이터 저장 19 | StringTokenizer st = new StringTokenizer(br.readLine()); 20 | int s = Integer.parseInt(st.nextToken()); 21 | int e = Integer.parseInt(st.nextToken()); 22 | tree[s].add(e); 23 | tree[e].add(s); 24 | } 25 | depth = new int[N + 1]; 26 | visited = new boolean[N + 1]; 27 | int temp = 1; 28 | kmax = 0; 29 | while (temp <= N) { // 최대 가능 Depth 구하기 30 | temp <<= 1; 31 | kmax++; 32 | } 33 | parent = new int[kmax + 1][N + 1]; 34 | BFS(1); // depth를 BFS를 통하여 구하기 35 | for (int k = 1; k <= kmax; k++) { 36 | for (int n = 1; n <= N; n++) { 37 | parent[k][n] = parent[k - 1][parent[k - 1][n]]; 38 | } 39 | } 40 | int M = Integer.parseInt(br.readLine()); // 질의의 수 41 | for (int i = 0; i < M; i++) { 42 | // 공통 조상을 구할 두 노드 43 | StringTokenizer st = new StringTokenizer(br.readLine()); 44 | int a = Integer.parseInt(st.nextToken()); 45 | int b = Integer.parseInt(st.nextToken()); 46 | int LCA = excuteLCA(a, b); 47 | System.out.println(LCA); 48 | } 49 | } 50 | static int excuteLCA(int a, int b) { 51 | if (depth[a] > depth[b]) {//더 깊이가 깊은 depth가 b가 되도록 변경해주기 52 | int temp = a; 53 | a = b; 54 | b = temp; 55 | } 56 | for (int k = kmax; k >= 0; k--){// depth 빠르게 맞춰주기 57 | if (Math.pow(2, k) <= depth[b] - depth[a]) { 58 | if (depth[a] <= depth[parent[k][b]]) { 59 | b = parent[k][b]; 60 | } 61 | } 62 | } 63 | for (int k = kmax; k >= 0 && a != b; k--) { // 조상 빠르게 찾기 64 | if (parent[k][a] != parent[k][b]) { 65 | a = parent[k][a]; 66 | b = parent[k][b]; 67 | } 68 | } 69 | int LCA = a; 70 | if (a != b) 71 | LCA = parent[0][LCA]; 72 | return LCA; 73 | } 74 | // BFS구현 75 | private static void BFS(int node) { 76 | Queue queue = new LinkedList(); 77 | queue.add(node); 78 | visited[node] = true; 79 | int level = 1; 80 | int now_size = 1; 81 | int count = 0; 82 | while (!queue.isEmpty()) { 83 | int now_node = queue.poll(); 84 | for (int next : tree[now_node]) { 85 | if (!visited[next]) { 86 | visited[next] = true; 87 | queue.add(next); 88 | parent[0][next] = now_node; // 부모 노드 저장 89 | depth[next] = level; // 노드 depth 저장 90 | } 91 | } 92 | count++; 93 | if (count == now_size) { 94 | count = 0; 95 | now_size = queue.size(); 96 | level++; 97 | } 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /트리/P11505_구간곱구하기.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.util.*; 3 | public class P11505_구간곱구하기 { 4 | static long[] tree; 5 | static int MOD; 6 | public static void main(String[] args) throws IOException { 7 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 8 | StringTokenizer st = new StringTokenizer(br.readLine()); 9 | int N = Integer.parseInt(st.nextToken()); // 수의 개수 10 | int M = Integer.parseInt(st.nextToken()); // 변경이 일어나는 횟수 11 | int K = Integer.parseInt(st.nextToken()); // 구간 곱을 구하는 횟수 12 | int treeHeight = 0; 13 | int lenght = N; 14 | while (lenght != 0) { 15 | lenght /= 2; 16 | treeHeight++; 17 | } 18 | int treeSize = (int) Math.pow(2, treeHeight + 1); 19 | int leftNodeStartIndex = treeSize / 2 - 1; 20 | MOD = 1000000007; 21 | tree = new long[treeSize + 1]; 22 | for (int i = 0; i < tree.length; i++) { //초기 값을 곱셈이기 때문에 1로 설정 23 | tree[i] = 1; 24 | } 25 | for (int i = leftNodeStartIndex + 1; i <= leftNodeStartIndex + N; i++) { 26 | tree[i] = Long.parseLong(br.readLine()); // 데이터를 리프노드에 입력 받기 27 | } 28 | setTree(treeSize - 1); // tree 만들기 29 | for (int i = 0; i < M + K; i++) { 30 | st = new StringTokenizer(br.readLine()); 31 | long a = Integer.parseInt(st.nextToken()); 32 | int s = Integer.parseInt(st.nextToken()); 33 | long e = Long.parseLong(st.nextToken()); 34 | if (a == 1) { // 변경 35 | changeVal(leftNodeStartIndex + s, e); 36 | } else if (a == 2) { // 구간 곱 37 | s = s + leftNodeStartIndex; 38 | e = e + leftNodeStartIndex; 39 | System.out.println(getMul(s, (int) e)); 40 | } else { 41 | return; 42 | } 43 | } 44 | br.close(); 45 | } 46 | // 모든 함수에서 곱셈이 발생할때 마다 MOD연산 수행 47 | private static long getMul(int s, int e) { 48 | long partMul = 1; 49 | while (s <= e) { 50 | if (s % 2 == 1) { 51 | partMul = partMul * tree[s] % MOD; 52 | s++; 53 | } 54 | if (e % 2 == 0) { 55 | partMul = partMul * tree[e] % MOD; 56 | e--; 57 | } 58 | s = s / 2; 59 | e = e / 2; 60 | } 61 | return partMul; 62 | } 63 | private static void changeVal(int index, long val) { 64 | tree[index] = val; 65 | while (index > 1) { //현재 노드의 양쪽 자식 노드를 찾아 곱해주는 로직 66 | index = index / 2; 67 | tree[index] = tree[index * 2] % MOD * tree[index * 2 + 1] % MOD; 68 | } 69 | } 70 | private static void setTree(int i) { 71 | while (i != 1) { 72 | tree[i / 2] = tree[i / 2] * tree[i] % MOD; 73 | i--; 74 | }}} -------------------------------------------------------------------------------- /트리/P11725_트리의부모찾기.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class P11725_트리의부모찾기 { 3 | static int N; 4 | static boolean[] visit; 5 | static ArrayList tree[]; 6 | static int answer[]; 7 | public static void main(String[] args) { 8 | Scanner sc = new Scanner(System.in); 9 | N = sc.nextInt(); 10 | visit = new boolean[N + 1]; 11 | tree = new ArrayList[N + 1]; 12 | answer = new int[N + 1]; 13 | for (int i = 0; i < tree.length; i++) { 14 | tree[i] = new ArrayList<>(); 15 | } 16 | for (int i = 1; i < N; i++) { 17 | int n1 = sc.nextInt(); 18 | int n2 = sc.nextInt(); 19 | tree[n1].add(n2); 20 | tree[n2].add(n1); 21 | } 22 | DFS(1); 23 | for (int i = 2; i <= N; i++) { 24 | System.out.println(answer[i]); 25 | } 26 | } 27 | static void DFS(int number) { 28 | visit[number] = true; 29 | for (int i : tree[number]) { 30 | if (!visit[i]) { 31 | answer[i] = number; 32 | DFS(i); 33 | } 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /트리/P14425_문자열찾기.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | public class P14425_문자열찾기 { 3 | public static void main(String[] args) { 4 | Scanner sc = new Scanner(System.in); 5 | int n = sc.nextInt(); 6 | int m = sc.nextInt(); 7 | tNode root = new tNode(); 8 | while (n > 0) { //트라이 자료구조 구축하기 9 | String text = sc.next(); 10 | tNode now = root; 11 | for (int i = 0; i < text.length(); i++) { 12 | char c = text.charAt(i); 13 | // 26개 알파벳의 위치를 배열 index로 나타내기 위세 -'a'수행 14 | if (now.next[c - 'a'] == null) { 15 | now.next[c - 'a'] = new tNode(); 16 | } 17 | now = now.next[c - 'a']; 18 | if (i == text.length() - 1) 19 | now.isEnd = true; 20 | } 21 | n--; 22 | } 23 | int count = 0; 24 | while (m > 0) { //트라이 자료구조 검색하기 25 | String text = sc.next(); 26 | tNode now = root; 27 | for (int i = 0; i < text.length(); i++) { 28 | char c = text.charAt(i); 29 | if (now.next[c - 'a'] == null) { // 공백노드이면 해당 문자열을 포함하지 않음 30 | break; 31 | } 32 | now = now.next[c - 'a']; 33 | if (i == text.length() - 1 && now.isEnd) // 문자열의 끝이고 현재까지 모두 일치하면 34 | count++; // S집합에 포함되는 문자열 35 | } 36 | m--; 37 | } 38 | System.out.println(count); 39 | } 40 | } 41 | class tNode { 42 | tNode[] next = new tNode[26]; 43 | boolean isEnd; // 문자열의 마지막 유무를 표시 44 | } 45 | -------------------------------------------------------------------------------- /트리/P1991_트리순회.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class P1991_트리순회 { 3 | static int[][] tree; 4 | public static void main(String args[]) { 5 | Scanner sc = new Scanner(System.in); 6 | int n = sc.nextInt(); 7 | sc.nextLine(); 8 | tree = new int[26][2]; // 0->왼쪽 자식 노드; 1->오른쪽 자식 노드 9 | for (int i = 0; i < n; i++) { 10 | String[] temp = sc.nextLine().split(" "); 11 | int node = temp[0].charAt(0) - 'A'; // index로 변환을 위해 A문자 빼주기 12 | char left = temp[1].charAt(0); 13 | char right = temp[2].charAt(0); 14 | // 자식 노드가 없을 경우 -1을 저장 15 | if (left == '.') { 16 | tree[node][0] = -1; 17 | } else { 18 | tree[node][0] = left - 'A'; 19 | } 20 | if (right == '.') { 21 | tree[node][1] = -1; 22 | } else { 23 | tree[node][1] = right - 'A'; 24 | } 25 | } 26 | preOrder(0); 27 | System.out.println(); 28 | inOrder(0); 29 | System.out.println(); 30 | postOrder(0); 31 | System.out.println(); 32 | } 33 | public static void preOrder(int now) { 34 | if (now == -1) 35 | return; 36 | System.out.print((char) (now + 'A')); // 1.현재 정점 37 | preOrder(tree[now][0]); // 2.왼쪽 탐색 38 | preOrder(tree[now][1]); // 3.오른쪽 탐색 39 | } 40 | public static void inOrder(int now) { 41 | if (now == -1) 42 | return; 43 | inOrder(tree[now][0]); // 1.왼쪽 탐색 44 | System.out.print((char) (now + 'A')); // 2.현재 정점 45 | inOrder(tree[now][1]); // 3.오른쪽 탐색 46 | } 47 | public static void postOrder(int now) { 48 | if (now == -1) 49 | return; 50 | postOrder(tree[now][0]); // 1.왼쪽 탐색 51 | postOrder(tree[now][1]); // 2.오른쪽 탐색 52 | System.out.print((char) (now + 'A')); // 2.현재 정점 53 | } 54 | } -------------------------------------------------------------------------------- /트리/P2042_구간합구하기3.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.util.*; 3 | public class P2042_구간합구하기3 { 4 | static long[] tree; 5 | public static void main(String[] args) throws IOException { 6 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 7 | StringTokenizer st = new StringTokenizer(br.readLine()); 8 | int N = Integer.parseInt(st.nextToken()); // 수의 개수 9 | int M = Integer.parseInt(st.nextToken()); // 변경이 일어나는 횟수 10 | int K = Integer.parseInt(st.nextToken()); // 구간 합을 구하는 횟수 11 | int treeHeight = 0; 12 | int lenght = N; 13 | while (lenght != 0) { 14 | lenght /= 2; 15 | treeHeight++; 16 | } 17 | int treeSize = (int) Math.pow(2, treeHeight + 1); 18 | int leftNodeStartIndex = treeSize / 2 - 1; 19 | tree = new long[treeSize + 1]; 20 | // 데이터를 리프노드에 입력 받기 21 | for (int i = leftNodeStartIndex + 1; i <= leftNodeStartIndex + N; i++) { 22 | tree[i] = Long.parseLong(br.readLine()); 23 | } 24 | setTree(treeSize - 1); // tree 만들기 25 | 26 | for (int i = 0; i < M + K; i++) { 27 | st = new StringTokenizer(br.readLine()); 28 | long a = Integer.parseInt(st.nextToken()); 29 | int s = Integer.parseInt(st.nextToken()); 30 | long e = Long.parseLong(st.nextToken()); 31 | 32 | if (a == 1) { // 변경 33 | changeVal(leftNodeStartIndex + s, e); 34 | } else if (a == 2) { // 구간 합 35 | s = s + leftNodeStartIndex; 36 | e = e + leftNodeStartIndex; 37 | System.out.println(getSum(s, (int) e)); 38 | } else { 39 | return; 40 | } 41 | } 42 | 43 | br.close(); 44 | } 45 | 46 | private static long getSum(int s, int e) { 47 | long partSum = 0; 48 | while (s <= e) { 49 | if (s % 2 == 1) { 50 | partSum = partSum + tree[s]; 51 | s++; 52 | } 53 | if (e % 2 == 0) { 54 | partSum = partSum + tree[e]; 55 | e--; 56 | } 57 | s = s / 2; 58 | e = e / 2; 59 | } 60 | return partSum; 61 | } 62 | 63 | private static void changeVal(int index, long val) { 64 | long diff = val - tree[index]; 65 | while (index > 0) { 66 | tree[index] = tree[index] + diff; 67 | index = index / 2; 68 | } 69 | } 70 | 71 | private static void setTree(int i) { 72 | while (i != 1) { 73 | tree[i / 2] += tree[i]; 74 | i--; 75 | } 76 | 77 | } 78 | 79 | } --------------------------------------------------------------------------------