Skip to content

Conversation

@0224LJH
Copy link
Contributor

@0224LJH 0224LJH commented May 16, 2025

🚀 싸피 15반 알고리즘 스터디 17주차 [이종환]

📌 문제 풀이 개요

  • 이번 PR에서는 다음 5문제의 풀이를 포함합니다.
  • 각 문제에 대한 풀이 과정과 접근 방식을 설명합니다.

✅ 문제 해결 여부

  • 문제 1: 어항 정리
  • 문제 2: 휴게소 세우기
  • 문제 3: 줄 세우기
  • 문제 4: 공통 부분 문자열
  • 문제 5: 전구와 스위치

💡 풀이 방법

문제 1: 어항 정리

문제 난이도
플레5

문제 유형
'구현' , '시뮬레이션'

접근 방식 및 풀이
처음에는 두개의 접는 방식을 공통 메서드로 구현하려 했었는데, 자세히 읽어보니 접는 방식이 달라서 각각 구현하였다. 인풋값이 엄청 큰 것이 아니기에 2차원 배열과 인덱스관리를 통해 접는 것과 그 후 분배를 구현하였다.

	private static void foldOne() {
		folded = new int[size][size];
		height=1; //기둥 높이. 처음에는 높이1짜리 기둥이 존재한다고 가정
		floor=1; //바닥 높이.
		cnt = 1; // 기둥 개수
		stIdx = 0;
		
		for (int i = 0; i < size; i++) folded[0][i] = arr[i];
		while(isValid()) {
			int nIdx = stIdx+cnt; // 기둥 말고 바닥의 첫번째 인덱스
			for (int j = 0; j < cnt; j++) {
				for (int i = 0; i < height; i++) {
					folded[cnt-j+floor-1][nIdx+i] = folded[i][j+stIdx];
					folded[i][j+stIdx] = 0;
				}
			}
			stIdx = height*cnt; // 이젠 nIdx가 첫번째 기둥의 위치가 됨
			if(height == cnt)height++;
			else cnt++;
		}
		redistributeAll();
	}
	private static void foldHalf() {
		folded = new int[size][size];
		// 4등분 했을 때, 각각으 파트가 시작하는 인덱스
		int[] pIdx = {0, size/4,(size/4)*2,(size/4)*3};
		int quater = size/4;
		for (int i = 0; i < quater; i++) {
			folded[0][pIdx[3]+i] = arr[pIdx[3]+i];
			folded[1][pIdx[3]+i] = arr[pIdx[1]-1-i];
			folded[2][pIdx[3]+i] = arr[pIdx[1]+i];
			folded[3][pIdx[3]+i] = arr[pIdx[3]-1-i];
		}
		
		redistributeAll();		
	}

문제 2: 휴게소 세우기

문제 난이도
골드4

문제 유형
이분 탐색

접근 방식 및 풀이
처음에는 그리디하게 접근하려고 했는데 계속해서 실패했다.
다시 생각해보니 특정 값이 정답인지 아닌지를 판단하는 데 소요되는 연산이 그리 심하지 않았기에, 이분탐색을 통해 N개 이하의 휴게소를 통해 만들 수 있는 최댓값 중 최솟값을 구하였다.

	private static void findMinMax() {
		int l = 1;
		int r = len+1;
		int mid = (l+r)/2; 
		while(l < r) {
			int cnt = getPlusCnt(mid);
			if (cnt > plusCnt) {
				// 목표보다 더 많이 세움 -> 설정길이가 너무 짧음. 더 늘려야함
				l = mid+1;
			} else if (cnt <= plusCnt) {
				// 목표보다 더 적게 세워지거나 같음 -> 설정길이를 더 줄여서 리트라이{
				ans = Math.min(ans, mid);
				
				r = mid;
			}
			mid = (l+r)/2; 
		}
	}

문제 3: 줄 세우기

문제 난이도
골드4

문제 유형
DP, LIS

접근 방식 및 풀이
전형적인 LIS 문제였다.
인풋값이 크지 않기에 O(N^2) 방식으로도
dp 테이블을 만들면 손쉽게 풀 수 있다.

		Arrays.fill(dp, 1);
		for (int i = 1; i < size; i++) {
			for (int j = 0; j <i; j++) {
				if (arr[i] < arr[j]) continue;
				dp[i] = Math.max(dp[i], dp[j]+1);
				
			}
		}
		int max = 1;
		for (int i = 0; i < size; i++) max = Math.max(max, dp[i]);

문제 4: 공통 부분 문자열

문제 난이도
골드5

문제 유형
dp, LCS

접근 방식 및 풀이
인풋의 길이가 4000이하여서 그냥 이중 for문을 통해 해결하였다. 이번 문제들 중 가장 쉬웠던 문제.

		for (int i = 0; i < input1.length; i++) {
			for (int j = 0; j < input2.length; j++) {
				if(input1[i].equals(input2[j])) {
					dp[i][j] = 1;
					if(i == 0 || j == 0) continue;
					
					dp[i][j] += dp[i-1][j-1];
					ans = Math.max(ans, dp[i][j]);
				}
			}
		}

문제 5: 전구와 스위치

문제 난이도
골드4

문제 유형
그리디

접근 방식 및 풀이
어항 다음으로 많은 시간을 쏟았다.
단순한 DP로는 안 풀리고, 일일히 완탐을 하는 것은 불가능 해보였다.
그런데 잘 생각해보니 결국 첫 스위치를 누른다/안 누른다 분기만 설정하면 그 다음 스위치는 입력값에 의해 자동으로 결정되었다. 이를 통해 풀이 자체는 간단하게 풀 수 있었다.

	private static void greedy() {
		for (int i = 1; i < len; i++) {
			int goal = flip[i-1]; // 이걸 맞춰줘야함
			int cur = (choice[i-1] + ((i > 1)?choice[i-2]:0))%2;// 이전 두개만으로의 상황
			choice[i] = Math.abs(goal-cur);
			
		}
		
		check();	
	}

	private static void check() {
		int temp = 0;
		for (int i = 0; i < len; i++) {
			temp += choice[i];
			int goal = flip[i];
			int cur = choice[i];
			
			if (i > 0) cur += choice[i-1];
			if (i < len-1) cur += choice[i+1];
			cur %= 2;

			if(goal != cur) return;
		}
		ans = Math.min(temp, ans);
		
	}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant