알고리즘/백준

[백준/c++] 18290번: NM과 K(1)

녕이 2022. 8. 4. 17:52
728x90

 

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

 

18290번: NM과 K (1)

크기가 N×M인 격자판의 각 칸에 정수가 하나씩 들어있다. 이 격자판에서 칸 K개를 선택할 것이고, 선택한 칸에 들어있는 수를 모두 더한 값의 최댓값을 구하려고 한다. 단, 선택한 두 칸이 인접

www.acmicpc.net

 

 

이 문제는 BackTracking인데, BFS/DFS의 dx, dy 유형을 가미한 것 같다.

BT에서 k개를 선택했으면 ans를 max value로 갱신하고 나가는 기저 조건은 동일한데, 여기서 인접 칸은 선택하면 안 되는 게 관건이다.

이를 위해서, 칸을 선택하기 전에 이 칸의 인접한 칸이 선택되어있는지 체크해줘야 한다.

인접칸이 선택되어있다면 이 칸은 선택하면 안 되기 때문! 

 

선택하지 않은 칸을 선택하고, 그 칸의 인접칸을 찾고 만약 지금까지 선택한 칸이 있다면(visit배열 값이 true일 것)

이 칸은 선택하면 안된다. 그러므로 flag 깃발을 꽂아서 이 칸을 선택하지 못하게 한다.

 

인접 칸들을 모두 보고 나서 만약 flag가 true라면 선택된 인접 칸이 없다는 뜻이므로 선택하고 BT로 들어가서 이어간다.

 

#include <iostream>
#include <algorithm>
using namespace std;
int n, m, k, arr[11][11], ans = -2147483648;
bool visit[11][11];
int dir[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};

void BT(int cnt, int sum){
    if(cnt == k){ //k개 선택 완료
        ans = max(ans, sum);
        return;
    }
    
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            if(!visit[i][j]){
                bool flag = true;
                for(int k=0; k<4; k++){
                    int dx = i + dir[k][0];
                    int dy = j + dir[k][1];
                    if(0<=dx&&dx<n&&0<=dy&&dy<m) if(visit[dx][dy]) flag = false;
                }
                if(flag){
                    visit[i][j] = true;
                    BT(cnt+1, sum+arr[i][j]);
                    visit[i][j] = false;
                }
            }
        }
    }
}

int main(){
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    cin >> n >> m >> k;
    for(int i=0; i<n; i++) for(int j=0; j<m; j++) cin >> arr[i][j];
    BT(0, 0);
    cout << ans << '\n';
    return 0;
}

 

 

 

 

728x90