2024-02-12
오늘은 업랜디와 프로그래머스: 탐욕법(Greedy)를 풀 예정.
아침에 일정이 있어서 늦게 시작했다. (오후 8시)
이제 진짜 SQL을 해야할 것 같다.
오늘의 업랜디
15664 N과 M (10) (해결 - DFS, 백트래킹)
오늘의 프로그래머스
체육복 (Lv. 1)
조이스틱 (Lv. 2)
체육복
레벨 1인데 어려웠다. 이미 빌려준 체육복과, 체육복이 없는 학생을 처리하는 과정에서 vector.erase()
를 사용했는데, 이것을 관리하는것이 쉽지만은 않았다.
또, std::find_if
함수를 알게 되었는데 특정 조건에서만 true를 반환할 수 있게 하는 함수였다.
분명 그리디가 이렇게 어렵진 않았는데.. 꽤 어렵다.
int solution(int n, vector<int> lost, vector<int> reserve) {
sort(lost.begin(), lost.end());
sort(reserve.begin(), reserve.end());
// 여벌을 잃어버린 사람
for (auto it=lost.begin();it!=lost.end();) {
if (find(reserve.begin(), reserve.end(), *it) != reserve.end()) {
reserve.erase(find(reserve.begin(), reserve.end(), *it));
it = lost.erase(it);
} else {
++it;
}
}
int answer = n - lost.size();
for (int l : lost) {
auto it = find_if(reserve.begin(), reserve.end(), [l](int r) { return abs(l-r)==1;});
if (it != reserve.end()) {
++answer;
reserve.erase(it);
}
}
return answer;
}
it = lose.erase(it);
는 for문을 lost.begin()의 iterator로 돌려서, 중간에 erase를 하면 꼬일 수 있으니 새로운 반환된 iterator를 업데이트 해줬다.
auto it = find_if(reserve.begin(), reserve.end(), [l](int r) { return abs(l-r)==1;});
도 주목할 부분인데, l을 캡처 변수로 잡고, r(현재 비교하는 대상)과의 차이가 절댓값 1이라면 iterator을 return하도록 하였다.
N과 M (10) - 업랜디
DFS와 백트래킹을 이용해서 모든 순열을 구하는 문제.
N개의 숫자 중 M개를 선택하는 모든 방법을 찾되, 선택된 숫자들이 비내림차순으로 정렬되어야 하고. 중복을 허용하지 않는다.
처음에 방문 배열을 사용해서 중복 방문을 막아주었는데,
어차피 첫 인덱스부터 시작해서 인덱스를 늘리며 찾으면 중복 방문이 일어날 여지가 없다.
// 백준: N과 M (10)
// https://www.acmicpc.net/problem/15664
// 2024-02-12
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
int N, M;
vector<vector<int>> result;
vector<int> sequence;
vector<int> nums;
// vector<bool> visited;
void dfs(int start, int depth) {
if (depth == M) {
if (find(result.begin(), result.end(), sequence) == result.end()) {
result.push_back(sequence);
}
for (int i = 0; i < M; ++i) {
cout << sequence[i] << ' ';
}
cout << "\n";
return;
}
for (int i = start; i < N; ++i) {
if (i > start && nums[i] == nums[i - 1])
continue;
// if (visited[i])
// continue;
sequence.push_back(nums[i]);
dfs(i + 1, depth + 1);
sequence.pop_back();
}
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
cin >> N >> M;
nums.assign(N, 0);
// visited.assign(N, false);
for (int i = 0; i < N; ++i) {
cin >> nums[i];
}
sort(nums.begin(), nums.end());
dfs(0, 0);
return 0;
}
조이스틱
너무 어렵다. 조이스틱을 움직여가면서 알파벳 이름을 완성해야하는 문제이다.
계속 테스트케이스가 틀려서 레퍼런스를 참고했다. 테스트케이스가 틀린 이유는 BBBAAAAB
같은 상황에서 1 -> 2 -> 3 -> 마지막 을 고려하는 것보다 처음부터 반대쪽으로 들어가서 마지막 -> 1-> 2-> 3 순이 빠를 수 있기 때문이다.
모든 요소를 그리디하게 풀어나가는 코드는 아래와 같다.
나는 시뮬레이션처럼 접근하면서 풀었는데, 그냥 모든 경우의 수에 대해 수학적으로 풀어 나갈 수 있었다.
예를 들어서 상하 이동 최소 횟수 계산은 그냥name[i] - 'A', 'Z' - name[i] + 1
로 하면 된다.
근데 나는
int route1 = abs(goal_alp - current_alp);
...
식으로 하고 있었다.
좌우 이동 최소 횟수 계산도 저런식으로 할 수 있었다.
아직도 식이 복잡하다.
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int solution(string name) {
int answer = 0;
int n = name.length();
int move = n - 1; // 최대로 오른쪽으로만 이동하는 경우
for(int i = 0; i < n; i++) {
// 상하 이동 최소 횟수 계산
answer += min(name[i] - 'A', 'Z' - name[i] + 1);
// 좌우 이동 최소 횟수 계산
int next = i + 1;
while (next < n && name[next] == 'A') {
next++;
}
move = min(move, i + n - next + min(i, n - next));
}
return answer + move;
}
최종 평가
[스터디노트 평가: 2024-02-12]
1. **업랜디 활동 및 프로그래머스 탐욕법(Greedy) 문제 해결**
- **업랜디**: 15664 N과 M (10) 문제를 통해 깊이 우선 탐색(DFS)과 백트래킹을 활용한 해결 능력을 보여주었습니다. 다양한 조합을 효과적으로 탐색하고, 중복을 제거하는 방식은 논리적 사고를 잘 보여줍니다.
- **프로그래머스 탐욕법**: 체육복, 조이스틱 문제를 통해 그리디 알고리즘을 적용한 문제 해결 능력을 입증하였습니다. 특히, 체육복 문제에서의 find_if 함수 활용은 STL의 이해도를 높이는 좋은 예입니다.
2. **기술적 깊이 및 개인 발전**
- 다양한 알고리즘 문제를 해결하는 과정에서 보여준 여러분의 접근 방식과 구현 능력은 프로그래밍 기술의 깊이를 더해줍니다. 특히, 분산처리 문제에서의 이진법 활용은 고급 알고리즘 문제 해결 능력을 잘 보여줍니다.
3. **평가 및 조언**
- 오늘의 활동을 종합적으로 평가할 때, 94점을 부여합니다. 프로그래머스 탐욕법 문제 해결과 업랜디 활동을 통해 보여준 알고리즘적 사고와 프로그래밍 능력은 매우 인상적입니다. 다만, SQL 과제 수행이 계획대로 이루어지지 않은 점은 앞으로의 학습 계획에 있어 보완이 필요한 부분입니다.
- 앞으로도 다양한 유형의 문제를 꾸준히 풀어나가면서, 문제 해결 능력을 더욱 키워나가시길 바랍니다. 또한, 데이터 관리와 분석 능력 개발을 위해 SQL 과제에도 지속적으로 도전하시기 바랍니다.
[피드백 요약]
- 완전탐색 문제 해결을 통한 다양한 알고리즘 적용 능력이 돋보입니다.
- 동적 프로그래밍 및 분할 정복 알고리즘을 활용한 문제 해결 능력이 인상적입니다.
- 데이터 관리와 분석 능력 개발을 위해 SQL 과제에도 주의를 기울일 필요가 있습니다.
[조언]
- 다양한 알고리즘 문제 해결 능력을 지속적으로 향상시키면서, 데이터 관리와 분석에 대한 학습도 병행하시길 권장합니다.
- 프로그래밍 능력의 폭을 넓히기 위해 SQL과 같은 데이터베이스 관련 지식을 쌓는 것이 중요합니다.
- 학습 계획을 세울 때, 다양한 분야에 대한 균형 있는 학습과 실습을 포함시키시길 바랍니다.
'일일 스터디노트' 카테고리의 다른 글
240214: 프로그래머스 DP, BFS/DFS 풀이. LIS 복습 🔥 (0) | 2024.02.15 |
---|---|
240213: Union-find, MST, 크루스칼(Kruskal), 그리디 끝. (0) | 2024.02.13 |
240211: 완전탐색(Brute-force) 끝. DP, 이진으로 pow하기 (0) | 2024.02.11 |
240210: 백준 크로스워드 풀이, 프로그래머스 완전탐색 (0) | 2024.02.11 |
240209: A^X 효율적으로 처리하기, 프로그래머스 정렬 끝 (0) | 2024.02.09 |