https://www.acmicpc.net/problem/15686
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.StringTokenizer;
public class Main {
static int n,m;
static int[][] selected;
static ArrayList<int[]> home = new ArrayList<>();
static ArrayList<int[]> chicken = new ArrayList<>();
static int min = Integer.MAX_VALUE;
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken());
m = Integer.parseInt(st.nextToken());
selected = new int[m][2];
for(int i=0;i<n;i++){
st = new StringTokenizer(br.readLine());
for(int j=0;j<n;j++){
int val = Integer.parseInt(st.nextToken());
if(val==2) chicken.add(new int[]{i,j});
else if(val == 1) home.add(new int[]{i,j});
}
}
comb(0,0);
System.out.println(min);
}
static void comb(int src, int tgt){
if(tgt == m){
// 최소값 거리 구하기 - bfs => 모든 경우의 수 중에 가장 적은 거리 출력
bfs();
return;
}
if(src == chicken.size()) return;
int[] cur = chicken.get(src);
selected[tgt][0] = cur[0];
selected[tgt][1] = cur[1];
comb(src+1, tgt+1);
comb(src+1, tgt);
}
static void bfs(){
int sum = 0;
for(int[] h:home){
int minDis = Integer.MAX_VALUE;
for(int i=0;i<m;i++){
int dis = Math.abs(h[0]-selected[i][0]) + Math.abs(h[1]-selected[i][1]);
minDis = Math.min(dis,minDis);
}
sum+=minDis;
}
min = Math.min(min,sum);
}
}
// 1. 이번 조합의 '도시 치킨 거리' 총합(sum)
// 2. 모든 '집'을 하나씩 순회
// 3. 각 '집'의 최소 치킨 거리(minDis)
// 4. '선택된 치킨집' M개를 순회
// 5. 현재 집과 현재 치킨집 사이의 맨해튼 거리 계산
// 6. 계산한 거리와 minDis를 비교해서 더 작은 값으로 갱신
// 7. (안쪽 for문이 끝나면,) 이 집의 최종 치킨 거리(minDis)가 정해짐
// 8. sum에 minDis를 더함
// 9. (바깥 for문이 끝나면,) 이번 조합의 '도시 치킨 거리'가 정해짐
// 10. 전역 변수인 최종 정답(min)과 비교해서 더 작은 값으로 갱신