[JAVA] 백준 15686번 치킨 배달
[HAVE TO DO]
STUDYING : JAVA
문제링크 : https://www.acmicpc.net/problem/15686
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
public class Main {
//집과 치킨집의 최장거리는 2(N-1)
static int N, M, count = 0, result = 987654321;
static int[][] map;
static List<Point> house = new ArrayList<Point>();
static List<Point> chicken = new ArrayList<Point>();
static boolean[] visited; //폐업시키지 않을 치킨집 선정
//집(x, y)과 치킨집(z, k) 사이의 거리 = |x-z| + |y-k|
//폐업시키는건 원래있던 치킨집 개수 중에 M개를 선택하고 나머지는 전부 폐업시킴
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st = new StringTokenizer(br.readLine());;
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
map = new int[N][N];
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < N; j++) {
map[i][j] = Integer.parseInt(st.nextToken());
if(map[i][j] == 1) house.add(new Point(i, j));
else if(map[i][j] == 2) chicken.add(new Point(i, j));
}
}
visited = new boolean[chicken.size()];
dfs(0);
bw.write(String.valueOf(result));
br.close();
bw.flush();
bw.close();
}
static void dfs(int index) {
visited[index] = true;
count++;
//치킨집을 M개 뽑았는가? = 맞다면 치킨거리 계산
if(count == M) {
int temp = 0;
//최소거리 계산
for (int i = 0; i < house.size(); i++) {
int dist = 987654321;
for (int j = 0; j < chicken.size(); j++) {
if(visited[j]) {
//만약 j번째 치킨집이 선택되었다면 집들이랑 거리를 계산함
dist = Math.min(dist, Math.abs(house.get(i).x - chicken.get(j).x) + Math.abs(house.get(i).y - chicken.get(j).y));
}
}
temp += dist;
}
result = Math.min(result, temp);
}
//갈 수 있는 곳을 순회
for (int i = index + 1; i < chicken.size(); i++) {
if(!visited[i]) {
dfs(i);
}
}
//체크아웃
count--;
visited[index] = false;
}
}
class Point{
int x;
int y;
public Point(int x, int y) {
super();
this.x = x;
this.y = y;
}
@Override
public String toString() {
return "[x=" + x + ", y=" + y + "]";
}
}
문제점 : 치킨집을 1개만 남기는 경우 1번째 치킨집만 선택한 후 dfs 빠져나옴
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
public class Main {
//집과 치킨집의 최장거리는 2(N-1)
static int N, M, count = 0, result = 987654321;
static int[][] map;
static List<Point> house = new ArrayList<Point>();
static List<Point> chicken = new ArrayList<Point>();
static boolean[] visited; //폐업시키지 않을 치킨집 선정
//집(x, y)과 치킨집(z, k) 사이의 거리 = |x-z| + |y-k|
//폐업시키는건 원래있던 치킨집 개수 중에 M개를 선택하고 나머지는 전부 폐업시킴
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st = new StringTokenizer(br.readLine());;
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
map = new int[N][N];
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < N; j++) {
map[i][j] = Integer.parseInt(st.nextToken());
if(map[i][j] == 1) house.add(new Point(i, j));
else if(map[i][j] == 2) chicken.add(new Point(i, j));
}
}
visited = new boolean[chicken.size()];
dfs(0);
bw.write(String.valueOf(result));
br.close();
bw.flush();
bw.close();
}
static void dfs(int index) {
visited[index] = true;
count++;
//치킨집을 M개 뽑았는가? = 맞다면 치킨거리 계산
if(count == M) {
int temp = 0;
//최소거리 계산
for (int i = 0; i < house.size(); i++) {
int dist = 987654321;
for (int j = 0; j < chicken.size(); j++) {
if(visited[j]) {
//만약 j번째 치킨집이 선택되었다면 집들이랑 거리를 계산함
dist = Math.min(dist, Math.abs(house.get(i).x - chicken.get(j).x) + Math.abs(house.get(i).y - chicken.get(j).y));
}
}
temp += dist;
}
result = Math.min(result, temp);
}
for (int i = index + 1; i < chicken.size(); i++) {
dfs(i);
}
visited[index] = false;
count--;
if(M == 1) {
for (int i = index + 1; i < chicken.size(); i++) {
dfs(i);
}
}
}
}
class Point{
int x;
int y;
public Point(int x, int y) {
super();
this.x = x;
this.y = y;
}
@Override
public String toString() {
return "[x=" + x + ", y=" + y + "]";
}
}
치킨집이 초기부터 1개인 경우를 따로 처리했지만 틀렸다고 떴다. 이 경우엔 모든 예시를 넣어서 맞았는데도 틀렸습니다가 떠서 너무 슬펐다ㅠㅠㅠㅠㅠ (얼마나 답답했으면 온라인 컴파일러도 써봤다...)
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
public class Main {
//집과 치킨집의 최장거리는 2(N-1)
static int N, M, result = 987654321;
static int[][] map;
static List<Point> house = new ArrayList<Point>();
static List<Point> chicken = new ArrayList<Point>();
static boolean[] visited; //폐업시키지 않을 치킨집 선정
//집(x, y)과 치킨집(z, k) 사이의 거리 = |x-z| + |y-k|
//폐업시키는건 원래있던 치킨집 개수 중에 M개를 선택하고 나머지는 전부 폐업시킴
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st = new StringTokenizer(br.readLine());;
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
map = new int[N][N];
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < N; j++) {
map[i][j] = Integer.parseInt(st.nextToken());
if(map[i][j] == 1) house.add(new Point(i, j));
else if(map[i][j] == 2) chicken.add(new Point(i, j));
}
}
visited = new boolean[chicken.size()];
dfs(0, 0);
bw.write(String.valueOf(result));
br.close();
bw.flush();
bw.close();
}
static void dfs(int index, int count) {
//치킨집을 M개 뽑았는가? = 맞다면 치킨거리 계산
if(count == M) {
int temp = 0;
//최소거리 계산
for (int i = 0; i < house.size(); i++) {
int dist = 987654321;
for (int j = 0; j < chicken.size(); j++) {
if(visited[j]) {
//만약 j번째 치킨집이 선택되었다면 집들이랑 거리를 계산함
dist = Math.min(dist, Math.abs(house.get(i).x - chicken.get(j).x) + Math.abs(house.get(i).y - chicken.get(j).y));
}
}
temp += dist;
}
result = Math.min(result, temp);
}
if(index == chicken.size()) {
return;
}
visited[index] = true;
dfs(index + 1, count + 1);
visited[index] = false;
dfs(index + 1, count);
}
}
class Point{
int x;
int y;
public Point(int x, int y) {
super();
this.x = x;
this.y = y;
}
@Override
public String toString() {
return "[x=" + x + ", y=" + y + "]";
}
}
그래서 아예 count를 따로 빼지 않고 치킨집 초기값이 1개가 아닌 경우는 count+1로 처리, 1개인 경우에는 count로 dfs 처리를 해주었다.
치킨집과 가정집의 좌표는 Point라는 class를 따로 만들어서 ArrayList에 넣어줬다.
'OTHER THINGS > STUDY STH' 카테고리의 다른 글
[JAVA] 백준 2042번 구간 합 구하기 (0) | 2020.09.03 |
---|---|
[JAVA] 백준 2014번 소수의 곱 (0) | 2020.08.29 |
[JAVA] 백준 1991번 트리 순회 (0) | 2020.08.22 |
[JAVA] 백준 1103번 게임 (0) | 2020.08.20 |
[JAVA] 백준 2580번 스도쿠 (0) | 2020.08.20 |