[BOJ] 2025년 11월 문제풀이 (5)
12/1/2025 · 6 min read
PS
글을 안쓴 기간동안 푼 양이 꽤 되기 때문에 골드 이상만 적는다..
1. [G3] Heights
- tag : math, geometry
헤론 정리를 쓰면 뚝딱이다.
using ld = long double;
ld ha, hb,hc;
void solve(){
ri(ha, hb, hc);
ld A = 1 / ha;
ld B = 1 / hb;
ld C = 1 / hc;
ld S = A + B + C;
ld area = 1 / sqrt(S _ (S - A _ 2) _ (S - B _ 2) _ (S - C _ 2));
po(area);
}
2. [G3] 약수 게임
- tag : math, number_theory, game_theory
두 소수의 곱이면 후공승, 이외엔 선공승
int n;
void solve(){
ri(n);
if(n == 1){
po("koosaga");
return;
}
vi res;
for(int i = 2; i *i <= n; i++){
while(n % i == 0) n /= i, res.pb(i);
}
if(n > 1) res.pb(n);
if(si(res) != 2) po("koosaga");
else po("cubelover");
}3. [G5] 최대 합 순서쌍의 개수
- tag : set, prefix_sum, hash_set
인덱스 저장하고 map으로 정리
int n;
map<int, vi> M;
void solve(){
ri(n);
vi v(n + 1);
for(int i = 1; i <= n; i++){
ri(v[i]);
M[v[i]].pb(i);
v[i] += v[i - 1];
}
int mx = 0, cnt = 1;
for(const auto& [a, b] : M){
int L = *b.begin(),R = *prev(b.end());
int S = v[R] - v[L - 1];
if(S > mx) mx = S,cnt = 1;
else if(S == mx) cnt++;
}
po(mx, cnt);
}
4. [G4] 수열의 점수
- tag : greedy
0, 1, 양수, 음수 이렇게 4개로 나눠서 처리하면 된다. 음수는 2개씩 짝지어서 처리하자.
ll n,res;
void solve(){
ri(n);
minpq<ll> mi;
maxpq<ll> pl;
for(int i = 0; i < n; i++){
int x; ri(x);
if(x == 1) res += x;
else{
if(x > 1) pl.push(x);
else if(x <= 0) mi.push(x);
}
}
while(si(pl) > 1){
auto a = pl.top(); pl.pop();
auto b = pl.top(); pl.pop();
res += (a * b);
}
while(si(mi) > 1){
auto a = mi.top(); mi.pop();
auto b = mi.top(); mi.pop();
res += (a * b);
}
while(!mi.empty()){
res += mi.top(); mi.pop();
}
while(!pl.empty()){
res += pl.top(); pl.pop();
}
po(res);
}5. [G5] 십자 찾기
- tag : prefix_sum
각 4방향에 대해서 누적합처리
int n,m,k,res, v[2555][2555][4];
void solve(){
ri(n, m, k);
for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++){
ri(v[i][j][0]);
v[i][j][3] = v[i][j][2] = v[i][j][1] = v[i][j][0];
}
for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++){
if(v[i][j][0]) v[i][j][0] += v[i][j - 1][0];
}
for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++){
if(v[i][j][1]) v[i][j][1] += v[i - 1][j][1];
}
for(int i = n; i > 0; i--) for(int j = m; j > 0; j--){
if(v[i][j][2]) v[i][j][2] += v[i][j + 1][2];
}
for(int i = n; i > 0; i--) for(int j = m; j > 0; j--){
if(v[i][j][3]) v[i][j][3] += v[i + 1][j][3];
if(v[i][j][0] > k and v[i][j][1] > k and v[i][j][2] > k and v[i][j][3] > k) res++;
}
po(res);
}6. [G5] 직사각형의 개수
- tag : data structure, brute force
대각선을 제외하고 카운팅해주면 된다. set or map이든 아무거나
int n,res;
set<pii> s;
pii v[5555];
void solve(){
ri(n);
for(int i = 0; i < n; i++){
ri(v[i].fi, v[i].se);
s.insert(v[i]);
}
for(int i = 0; i < n; i++){
auto [x1, y1] = v[i];
for(int j = i + 1; j < n; j++){
auto [x2, y2] = v[j];
if(x1 == x2 or y1 == y2) continue;
if(s.count({x1, y2}) and s.count({x2, y1})) res++;
}
s.erase(v[i]);
}
po(res);
}7. [G4] 점프
- tag : bfs
BFS를 잘 짜자
int n,m,g[10101];
bool bound(int x){ return x < 0 or x > n; }
int D[3] = {-1, 0, 1};
void solve(){
ri(n, m);
while(m--){
int x; ri(x); g[x] = 1;
}
vvi dist(n + 1, vi(500, -1));
queue<pii> q;
dist[1][0] = 0; q.push({0, 1}); // 몇번 이동, 위치
while(si(q)){
auto [cnt, cur] = q.front(); q.pop();
if(cur == n){
po(dist[cur][cnt]);
return;
}
for(int i = 0; i < 3; i++){
auto ncnt = cnt + D[i];
auto nxt = cur + ncnt;
if(ncnt < 1) continue;
if(bound(nxt)) continue;
if(g[nxt]) continue;
if(dist[nxt][ncnt] != -1) continue;
dist[nxt][ncnt] = dist[cur][cnt] + 1; q.push({ncnt, nxt});
}
}
po(-1);
}8. [G2] 게임
- tag : dp, graph, dfs
사이클 찾고 최장거리 DP
int n,m,mx;
bool bound(int x, int y){ return x < 0 or x >= n or y < 0 or y >= m; }
string v[55];
bool vist[55][55], finished[55][55];
bool cycle = 0;
int D[55][55];
void dfs(int x, int y){
vist[x][y] = 1;
for(int d = 0; d < 4; d++){
int k = v[x][y] - '0';
int nx = x + k * dx[d], ny = y + k * dy[d];
if(bound(nx, ny) or v[nx][ny] == 'H') continue;
if(vist[nx][ny]){
if(!finished[nx][ny]) cycle = 1;
}
else dfs(nx, ny);
}
finished[x][y] = 1;
}
int dp(int x, int y){
int& ret = D[x][y];
if(ret != -1) return ret;
ret = 1;
int k = v[x][y] - '0';
for(int d = 0; d < 4; d++){
int nx = x + k * dx[d], ny = y + k * dy[d];
if(bound(nx, ny) or v[nx][ny] == 'H') continue;
ret = max<int>(ret, dp(nx, ny) + 1);
}
return ret;
}
void solve(){
ri(n, m);
for(int i = 0; i < n; i++) ri(v[i]);
dfs(0, 0);
if(cycle){
po(-1);
return;
}
memset(D, -1, sizeof(D));
po(dp(0, 0));
}