1. n^2 배열 자르기
규칙 찾기 문제였다.
n = 3이 주어졌다고 하자. 그러면 arr는 아래 그림과 같다.
1 2 3
2 2 3
3 3 3
idx에 따른 값은 아래와 같다.
(0,0) : 1
(1,0), (1,1), (0,1) : 2
(2, 0), (2, 1), (2,2), (1,2), (0,2) : 3
보이는가? arr[i][j] = max(i, j) + 1이다.
또, n이 주어졌을 때, 특정 idx가 주어지면 배열의 그것으로 바꿀 수 있겠는가? -> Yes.
n/4, n%4로 바꿀 수 있다.
2. 방문 길이
중복되는 경우는 세지 않으니, map이나 set으로 풀면 되는 문제다.
그리고 팁. 이 문제와 같이 좌표평면에서 상하좌우로 이동하는 경우, if나 case를 써서 나누지 말고 아래와 같은 방법을 쓰자. 좀 더 간단하게 이동을 표현할 수 있다.
int dx[4] = {1, -1, 0, 0};
int dy[4] = {0, 0, 1, -1};
for(int i = 0; i<4; i++){
x += dx[i];
y += dy[i];
}
3. 이진 변환 반복하기
단순 구현 문제다.
4. 점프와 텔레포트
2진법 변환 문제다. (규칙찾기)
5. 게임 맵 최단거리
DFS/BFS로 풀 수 있는 문제다. 안 건든 지 오래되었다보니 조금 어렵다...
일단 DFS의 경우, 모든 경우의 수를 따져봐야 하기 때문에 시간초과가 난다. 따라서 최단거리 탐색 했을 때 해가 보이는 BFS로 탐색을 하는 게 더 빠른 시간 내에 가능할 것이다. 일단 코드는 BFS, DFS 둘 다 올린다. 많이 더럽지만 이 코드를 반면교사 삼아 발전해 나갈 것이다.
// 게임 맵 최단거리
#include<vector>
#include <queue>
int dr[4] = {1, -1, 0, 0};
int dc[4] = {0, 0, 1, -1};
using namespace std;
typedef pair<int, int> pii;
void BFS(pii max_rc, pii init_point, vector<vector<int>>& maps, vector<vector<int>>& dist, vector<vector<bool>>& visited){
queue<pii> q;
q.push(init_point);
dist[init_point.first][init_point.second] = 1;
visited[init_point.first][init_point.second] = true;
while(!q.empty()){
pii cur_point = q.front(); q.pop();
if(cur_point == max_rc){
return;
}
for(int i = 0; i<4; i++){
pii next_point = cur_point;
next_point.first += dr[i];
next_point.second += dc[i];
if(0 <= next_point.first && next_point.first <= max_rc.first && 0 <= next_point.second && next_point.second <= max_rc.second && maps[next_point.first][next_point.second] && !visited[next_point.first][next_point.second]){
q.push(next_point);
dist[next_point.first][next_point.second] = dist[cur_point.first][cur_point.second] + 1;
visited[next_point.first][next_point.second] = true;
}
}
}
}
int solution(vector<vector<int>> maps)
{
pii max_rc = {maps.size(), maps[0].size()};
vector<vector<int>> dist(max_rc.first, vector<int>(max_rc.second, -1));
vector<vector<bool>> visited(max_rc.first, vector<bool>(max_rc.second, false));
BFS({max_rc.first-1, max_rc.second-1}, {0, 0}, maps, dist, visited);
return dist[max_rc.first-1][max_rc.second-1];
}
// BFS ? -> 도달하면 바로 종료 및 해당 값 return. 이게 더 좋을 것임.
// DFS ? -> 모든 탐색 해 보아야 함. 오랜만에 DFS 쓰니까 너무 헷갈린당.
/*
void DFS(int max_r, int max_c, int r, int c, vector<vector<int>>& maps, vector<vector<bool>>& visited, vector<vector<int>>& dist, int cur_dist){
if(r == max_r && c == max_c){
dist[r][c] = min(dist[r][c], cur_dist);
return;
}
dist[r][c] = cur_dist;
for(int i = 0; i<4; i++){
int tempr = r + dr[i];
int tempc = c + dc[i];
if(0 <= tempr && tempr <= max_r && 0 <= tempc && tempc <= max_c && maps[tempr][tempc] == 1 && !visited[tempr][tempc]){
visited[tempr][tempc] = true;
DFS(max_r, max_c, tempr, tempc, maps, visited, dist, cur_dist+1);
visited[tempr][tempc] = false;
}
}
}
int solution(vector<vector<int>> maps)
{
int max_r = maps.size(), max_c = maps[0].size();
vector<vector<bool>> visited(max_r, vector<bool>(max_c, false));
vector<vector<int>> dist(max_r, vector<int>(max_c, -1));
dist[max_r-1][max_c-1] = 1000000;
DFS(max_r-1, max_c-1, 0, 0, maps, visited, dist, 1);
int answer = dist[max_r-1][max_c-1];
return answer == 1000000? -1 : answer;
}
*/
6. 스킬트리
skill tree가 성립하려면, skill 문자열 안에 있는 순서대로 skill이 있어야 한다. 문제 예시를 들자면 CBD라면 허용되는 skill은
(공백)
C
CB
CBD
이러한 순서로만 허용된다. 따라서 skill tree안에 있는 문자열 중, skill 내부에 있는 문자들만 순서를 유지한 채로 뽑을 것이다. 이 문자열들이 skill.substr(0, x), 0 <= x <= skill.length()를 만족하는지 확인하면 될 것이다.
// 스킬트리
#include <set>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int solution(string skill, vector<string> skill_trees) {
set<char> skill_set;
set<string> tree_set;
for(int i = 0; i<skill.length(); i++){
skill_set.insert(skill[i]);
tree_set.insert(skill.substr(0, skill.length()-i));
}
int answer = 0;
for(string s : skill_trees){
string result = "";
for(char c : s){
if(skill_set.find(c) != skill_set.end()){
result += c;
}
}
if(tree_set.find(result) != tree_set.end() || result == "") answer++;
}
return answer;
}
7. 영어 끝말잇기
set(중복 여부 판단)과 string의 front(), back() 함수를 알고 있다면 아주 쉽게 풀 수 있는 문제였다.
8. 괄호 회전하기
stack 기본 + substr을 사용할 수 있는지 문제이다.
9. 예상 대진표
a와 b가 같은 그룹에 있을 때까지 2로 나눠주면 되는 문제다. 같은 그룹의 판단을 어떻게 하느냐? cnt를 0으로 두고, a==b가 될때까지 돌리면 된다.
#include <iostream>
using namespace std;
int solution(int n, int a, int b)
{
int cnt = 0;
a--; b--;
while(a != b){
a/=2; b/=2;
cnt++;
}
/*do{
if(a&1) a++; if(b&1) b++;
a/=2; b/=2;
cnt++;
}while(abs(a-b) != 0);*/
return cnt;
}
'PS > PS Log' 카테고리의 다른 글
22.04.07. 풀었던 문제들 (0) | 2022.06.23 |
---|---|
22.04.06. 풀었던 문제들 (0) | 2022.06.22 |
22.04.04 풀었던 문제들 (0) | 2022.06.22 |
22.04.02. 풀었던 문제들 (0) | 2022.06.22 |
22.04.01. 풀었던 문제들 (0) | 2022.06.22 |