[백준] 14620번 꽃길 (C++)

2025. 8. 28. 17:06·Algorithm
728x90

https://www.acmicpc.net/problem/14620

 

 

이 문제는 N X N 격자가 주어졌을때 3개의 꽃잎을 놓았을 때 놓는 최소 비용을 구하는 문제이다.

 

그림을 자세히 보면 꽃잎을 놓는 정점에서 상하좌우로 1칸씩 퍼져서 꽃 모양을 완성하는 것을 알 수 있다.

 

이때 유의해야 할 점은 꽃끼리 겹치면 안되며 가장자리 칸같은 경우도 상, 하, 좌, 우 중 2개의 요소 이하를 벗어나기 때문에

포함할 수 없다.

 

최소 비용을 구하기위해서 그리디하게 가장 작은 격자 요소를 찾는다고 해도 이것이 최소 비용이 아닐 수 있기 때문에 다른 접근을 해봐야 한다.

 

N의 최대 크기가 10이기 때문에 100칸의 모든 경우의 수를 구하기엔 충분하다

O(100C3) 1억에 충분히 포함된다.

 

격자판의 모양이기 때문에 나는 dfs + 백트래킹을 사용하여 모든 경우의 수를 구하며 최솟값을 계속 update 해주었다.

 

 

정답코드

#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
typedef long long ll;
#define endl "\n"
#define MAX 1e9

struct coordinate {
    int x;
    int y;
    int r;
};

struct nutrition {
    int p;
    int f;
    int s;
    int v;
    int cost;
};

int dx[] = {0 ,0, -1, 0, 1, 1, -1, -1, 1};
int dy[] = {0, -1, 0, 1, 0, -1, 1, -1, 1};
int N;
int graph[11][11];
bool visited[11][11];
int result = MAX;

bool cando(int x, int y) {
    for(int i = 0; i < 5; i++) {
        int nx = x + dx[i];
        int ny = y + dy[i];

        if(nx < 0 || nx >= N || ny < 0 || ny >= N) return false;

        if(visited[nx][ny]) return false;
    }
    return true;
}

int extractcost(int x, int y) {
    int cost = 0;

    for(int i = 0; i < 5; i++) {
        int nx = x + dx[i];
        int ny = y + dy[i];

        cost += graph[nx][ny];
    }

    return cost;
}

void placeflower(int x, int y, int status) {
    if(status == 0) {
        for(int i = 0; i < 5; i++) { 
            int nx = x + dx[i];
            int ny = y + dy[i];

            visited[nx][ny] = true;
        }
    }
    else {
        for(int i = 0; i < 5; i++) {
            int nx = x + dx[i];
            int ny = y + dy[i];

            visited[nx][ny] = false;
        }
    }
}

void bt(int cnt, int totalcost) {
    if(cnt == 3) {
        result = min(result, totalcost);
        return;
    }

    for(int i = 1; i < N-1; i++) {
        for(int j = 1; j < N-1; j++) {
            if(cando(i, j)) {
                placeflower(i, j, 0);
                int tmpcost = extractcost(i, j);
                bt(cnt+1, totalcost + tmpcost);
                placeflower(i, j, 1);
            }
        }
    }
}

void solve() {
    bt(0, 0);

    cout << result;
}

void input() {
    cin >> N;

    for(int i = 0; i < N; i++) {
        for(int j = 0; j < N; j++) {
            cin >> graph[i][j];
        }
    }
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);

    input();
    solve();
}

 

코드를 하나씩 살펴보자

 

void bt(int cnt, int totalcost) {
    if(cnt == 3) {
        result = min(result, totalcost);
        return;
    }

    for(int i = 1; i < N-1; i++) {
        for(int j = 1; j < N-1; j++) {
            if(cando(i, j)) {
                placeflower(i, j, 0);
                int tmpcost = extractcost(i, j);
                bt(cnt+1, totalcost + tmpcost);
                placeflower(i, j, 1);
            }
        }
    }
}

 

먼저 bt함수는 모든 경우의 수를 구하는 재귀 형식의 함수이며 매개변수로 (꽃을 심었던 개수, 현재까지 꽃을 심은 비용)

으로 호출하였다.

cnt 즉 꽃을 심은 개수가 3일경우 totalcost와 정답을 비교하여 작은것으로 update 해주었다.

 

bool cando(int x, int y) {
    for(int i = 0; i < 5; i++) {
        int nx = x + dx[i];
        int ny = y + dy[i];

        if(nx < 0 || nx >= N || ny < 0 || ny >= N) return false;

        if(visited[nx][ny]) return false;
    }
    return true;
}

 

두번째로 cando 함수이다. 이 함수는 bt함수에서 격자 요소를 탐색하면서 놓을 수 있는지 없는지 이 함수가 판별하는 것이다.

현재 좌표와 그 좌표에서 상하좌우를 탐색해서 놓을 수 있는 경우 true

하나라도 벗어나는 경우 false를 반환하여 판별하였다.

 

int extractcost(int x, int y) {
    int cost = 0;

    for(int i = 0; i < 5; i++) {
        int nx = x + dx[i];
        int ny = y + dy[i];

        cost += graph[nx][ny];
    }

    return cost;
}

 

extractcost 함수는 cando에서 놓을 수 있는경우 그 놓을 수 있는 위치의 합을 계산하여 값을 넘겨주는 함수이다.

 

void placeflower(int x, int y, int status) {
    if(status == 0) {
        for(int i = 0; i < 5; i++) { 
            int nx = x + dx[i];
            int ny = y + dy[i];

            visited[nx][ny] = true;
        }
    }
    else {
        for(int i = 0; i < 5; i++) {
            int nx = x + dx[i];
            int ny = y + dy[i];

            visited[nx][ny] = false;
        }
    }
}

 

placeflower 함수는 현재 놓았던 꽃을 다시 탐색하지 않기 위해서 방문체크를 해주는 함수이다.

따라서 놓을때는 방문체크를 해주고 다시 탐색할때는 방문체크를 해제하여 다시 탐색할 수 있게 하였다.

 

728x90
저작자표시 (새창열림)

'Algorithm' 카테고리의 다른 글

[백준] 14395번 4연산 (C++)  (0) 2025.08.30
[백준] 13265번 색칠하기 (C++)  (0) 2025.08.29
[백준] 25381번 ABBC (C++)  (0) 2025.08.27
[백준] 1068번 트리 (C++)  (0) 2025.08.26
[백준] 2234번 성곽 (C++)  (0) 2025.08.25
'Algorithm' 카테고리의 다른 글
  • [백준] 14395번 4연산 (C++)
  • [백준] 13265번 색칠하기 (C++)
  • [백준] 25381번 ABBC (C++)
  • [백준] 1068번 트리 (C++)
쿨쿨.
쿨쿨.
  • 쿨쿨.
    All of the life
    쿨쿨.
  • 전체
    오늘
    어제
    • 분류 전체보기 (285) N
      • Programming (52) N
        • C, C++ (18)
        • Python (6)
        • Java (1)
        • HTML,CSS,JS (3)
        • SQL(DB) (13)
        • SpringBoot (8) N
        • Android (2)
        • CI,CD (1)
      • Algorithm (173)
        • Review (4)
      • Security (14)
        • WebHacking (3)
        • Websecurity (11)
      • OS (19)
        • Linux (12)
        • Mac os (2)
      • 머신러닝 (1)
      • CS(Computer Science) (12)
        • 컴퓨터 네트워크 (3)
        • 컴퓨터 구조 (1)
        • 인공지능 (8)
      • Docker (2) N
      • Dev Book Review (3)
        • Clean Code (1)
        • Effective Java (0)
        • Real MySQL (2)
      • SWM (1)
      • Review (6)
      • AWS (2)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    다익스트라
    누적합
    DFS
    백트래킹
    에라토스테네스의 체
    트리
    그래프 이론
    그리디
    BFS
    코딩
    구현
    linux
    Leviathan
    c언어
    깊이우선탐색
    시뮬레이션
    정렬
    재귀
    브루트포스
    백준
    WebSecurity
    wargame
    비트마스킹
    이분탐색
    우선순위 큐
    다이나믹 프로그래밍
    투포인터
    우선순위큐
    Bandit
    DP
  • 최근 댓글

  • 최근 글

  • 250x250
  • hELLO· Designed By정상우.v4.10.6
쿨쿨.
[백준] 14620번 꽃길 (C++)
상단으로

티스토리툴바