문제 링크 : www.acmicpc.net/problem/15686
내 풀이1(2021.1.28.) : BFS, 조합
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <limits.h>
using namespace std;
typedef pair<int, int> int_pair;
vector<int_pair> list;
vector<int> index;
int map[51][51];
int visit[51][51];
int N, M;
int cnt = 0;
int mi = INT_MAX;
void initialize_visit() {
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
visit[i][j] = 0;
}
}
}
void show() {
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
cout << map[i][j] << " ";
}
cout << endl;
}
cout << endl;
}
int bfs(int sy, int sx) {
int dy[] = { 0,0,-1,1 };
int dx[] = { -1,1,0,0 };
queue<int_pair> q;
q.push(make_pair(sy, sx));
visit[sy][sx] = 1;
int cnt = -1;
while (!q.empty()) {
int sz = q.size();
cnt++;
for (int j = 0; j < sz; j++) {
int_pair p = q.front(); q.pop();
int y = p.first;
int x = p.second;
if (map[y][x] == 2) {
initialize_visit();
return cnt;
}
for (int i = 0; i < 4; i++) {
int ny = y + dy[i];
int nx = x + dx[i];
if (ny <= 0 || nx <= 0 || ny > N || nx > N) continue;
if (visit[ny][nx] == 1) continue;
q.push(make_pair(ny, nx));
visit[ny][nx] = 1;
}
}
}
}
void combination(vector<int>& index, int n, int r) {
vector<int> selection;
for (int i = 0; i < r; i++) selection.push_back(1);
for (int i = 0; i < n - r; i++) selection.push_back(0);
do {
for (int i = 0; i < index.size(); i++) {
if (selection[i] == 1) {
int y = list[index[i]].first;
int x = list[index[i]].second;
map[y][x] = 2;
}
}
int total = 0;
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
if (map[i][j] != 1) continue;
total += bfs(i, j);
}
}
mi = min(mi, total);
for (int i = 0; i < index.size(); i++) {
if (selection[i] == 1) {
int y = list[index[i]].first;
int x = list[index[i]].second;
map[y][x] = 0;
}
}
} while (prev_permutation(selection.begin(), selection.end()));
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin >> N >> M;
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
int temp; cin >> temp;
if (temp == 2) {
cnt++;
list.push_back(make_pair(i, j));
}
else map[i][j] = temp;
}
}
for (int i = 0; i < cnt; i++) {
index.push_back(i);
}
combination(index, cnt, M);
cout << mi;
return 0;
}
결과 : 시간 초과
BFS로 풀 필요 없는 문제였다. 거리를 구할 때, 단순히 뺄셈의 절댓값을 계산하면 되기 때문이다.
조합으로 푸는 문제인데, 조합은 나처럼 STL의 permutation을 이용해도 되지만, DFS를 이용할 수도 있다고 한다.
참고로, 순열과 조합 모두 DFS로 구현할 수 있다고 한다.
참고1 : jaimemin.tistory.com/1059
참고2 : data-make.tistory.com/355
풀이에 참고한 링크 : www.acmicpc.net/board/view/55130
내 풀이2(2021.1.28.) : 조합
#include <iostream>
#include <algorithm>
#include <vector>
#include <limits.h>
#include <cstdlib>
using namespace std;
typedef pair<int, int> int_pair;
vector<int_pair> list;
vector<int> index;
int map[51][51];
int N, M;
int cnt = 0;
int mi = INT_MAX;
void combination(vector<int>& index, int n, int r) {
vector<int> selection;
for (int i = 0; i < r; i++) selection.push_back(1);
for (int i = 0; i < n - r; i++) selection.push_back(0);
do { // 특정 맵에 대하여
int total = 0;
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
if (map[i][j] != 1) continue;
int m = INT_MAX;
for (int k = 0; k < index.size(); k++) { // 선택된 r개의 치킨집에 대하여
if (selection[k] == 1) { // 선택된 1개의 치킨집에 대하여
int y = list[index[k]].first;
int x = list[index[k]].second;
m = min(m, abs(y - i) + abs(x - j));
}
}
total += m;
}
}
mi = min(mi, total);
} while (prev_permutation(selection.begin(), selection.end()));
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin >> N >> M;
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
int temp; cin >> temp;
if (temp == 2) {
cnt++;
list.push_back(make_pair(i, j));
}
else map[i][j] = temp;
}
}
for (int i = 0; i < cnt; i++) {
index.push_back(i);
}
combination(index, cnt, M);
cout << mi;
return 0;
}
결과 : 성공
사실 내 풀이처럼 맵을 그릴 필요도 없는 문제였다.
1의 좌표와 2의 좌표들을 벡터에 담기만 하면 풀 수 있다고 한다.
'알고리즘 > 조합, 순열' 카테고리의 다른 글
백준 15657번 : N과 M (8) (0) | 2021.01.29 |
---|---|
STL을 이용한 조합과 순열 코드 (0) | 2021.01.28 |
프로그래머스 스킬 체크 (레벨2) - 조합 문제 (0) | 2021.01.19 |