코딩테스트/Java

[JAVA] 백준 스타트택시

SK_MOUSE 2021. 6. 16. 16:25

dfs방식으로 문제를 풀었는데 시간초과가 됐다.

더보기
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.*; class Main { ​​​​static boolean[][] visit; ​​​​static int[][] grid; ​​​​static int N, M, fuel; ​​​​static int taxiX, taxiY; ​​​​static Guest[] guests; ​​​​public static void main(String[] args) throws IOException { ​​​​​​​​BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); ​​​​​​​​StringTokenizer st = new StringTokenizer(br.readLine()); ​​​​​​​​N = Integer.parseInt(st.nextToken()); ​​​​​​​​M = Integer.parseInt(st.nextToken()); ​​​​​​​​fuel = Integer.parseInt(st.nextToken()); ​​​​​​​​visit = new boolean[N][N]; ​​​​​​​​grid = new int[N][N]; ​​​​​​​​guests = new Guest[M]; ​​​​​​​​for (int i = 0; i < N; i++) { ​​​​​​​​​​​​st = new StringTokenizer(br.readLine()); ​​​​​​​​​​​​for (int j = 0; j < N; j++) { ​​​​​​​​​​​​​​​​grid[i][j] = Integer.parseInt(st.nextToken()); ​​​​​​​​​​​​} ​​​​​​​​} ​​​​​​​​st = new StringTokenizer(br.readLine()); ​​​​​​​​taxiY = Integer.parseInt(st.nextToken())-1; ​​​​​​​​taxiX = Integer.parseInt(st.nextToken())-1; ​​​​​​​​for(int i=0; i<M; i++){ ​​​​​​​​​​​​st = new StringTokenizer(br.readLine()); ​​​​​​​​​​​​int a=Integer.parseInt(st.nextToken())-1; ​​​​​​​​​​​​int b=Integer.parseInt(st.nextToken())-1; ​​​​​​​​​​​​int c=Integer.parseInt(st.nextToken())-1; ​​​​​​​​​​​​int d=Integer.parseInt(st.nextToken())-1; ​​​​​​​​​​​​guests[i] = new Guest(a,b,c,d); ​​​​​​​​} ​​​​​​​​for(int i=0; i<M; i++){ ​​​​​​​​​​​​int reFill = selectGuest(); ​​​​​​​​​​​​if(reFill<0){//앵꼬 ​​​​​​​​​​​​​​​​System.out.println(-1); ​​​​​​​​​​​​​​​​return; ​​​​​​​​​​​​} ​​​​​​​​​​​​fuel+= reFill; ​​​​​​​​​​​​//System.out.println(i+"번째 남은연료:" + fuel); ​​​​​​​​} ​​​​​​​​System.out.println(fuel); ​​​​} ​​​​static int selectGuest(){ ​​​​​​​​int minDistFromTaxi = Integer.MAX_VALUE; ​​​​​​​​int guestNum=0; ​​​​​​​​for(int i=0; i<M; i++){ ​​​​​​​​​​​​minDist = Integer.MAX_VALUE; ​​​​​​​​​​​​Guest g = guests[i]; ​​​​​​​​​​​​if(g.visit){//방문한곳 ​​​​​​​​​​​​​​​​continue; ​​​​​​​​​​​​} ​​​​​​​​​​​​shortestPath(taxiX, taxiY, g.sx, g.sy, 0);//출발점구하고 ​​​​​​​​​​​​//System.out.println(count); ​​​​​​​​​​​​count=0; ​​​​​​​​​​​​if(minDistFromTaxi>minDist){//------------------<거리가 서로 다른경우> ​​​​​​​​​​​​​​​​//System.out.println("-->" + minDist+"목표위치"+ g.sx+","+ g.sy); ​​​​​​​​​​​​​​​​guestNum=i;//몇번째 게스트인지.저장 ​​​​​​​​​​​​​​​​minDistFromTaxi=minDist; ​​​​​​​​​​​​}else if(minDistFromTaxi== minDist){//---------<거리가 서로 같은경우 비교> ​​​​​​​​​​​​​​​​//System.out.println(minDistFromTaxi + " vs " + minDist); ​​​​​​​​​​​​​​​​if(guests[guestNum].sy > g.sy){//1. 행값 작은걸로 ​​​​​​​​​​​​​​​​​​​​guestNum=i; ​​​​​​​​​​​​​​​​}else if(guests[guestNum].sy < g.sy) guestNum=guestNum;//그대로 ​​​​​​​​​​​​​​​​else{//2. 열값 작은걸로 ​​​​​​​​​​​​​​​​​​​​if(guests[guestNum].sx > g.sx){//1. 행값 작은걸로 ​​​​​​​​​​​​​​​​​​​​​​​​guestNum=i; ​​​​​​​​​​​​​​​​​​​​}else if(guests[guestNum].sx < g.sx) guestNum=guestNum; ​​​​​​​​​​​​​​​​} ​​​​​​​​​​​​} ​​​​​​​​} ​​​​​​​​//ystem.out.println("방문한곳 : " + guestNum); ​​​​​​​​guests[guestNum].visit=true;//방문했으니 바꿔주고 ​​​​​​​​//택시 ​​​​​​​​fuel-=minDistFromTaxi;//데릴러가기 ​​​​​​​​if(fuel<0) return -9999999;//만약 데릴러가다 앵꼬 ​​​​​​​​int consumedFuel = gotoGoal(guestNum); ​​​​​​​​fuel-= consumedFuel; ​​​​​​​​if(fuel<0) return -9999999;//만약 데려다주다 앵꼬 ​​​​​​​​return consumedFuel*2; ​​​​} ​​​​static int gotoGoal(int gNum){//데려다주기 ​​​​​​​​Guest g = guests[gNum]; ​​​​​​​​minDist=Integer.MAX_VALUE;//초기화 ​​​​​​​​shortestPath(g.sx, g.sy, g.dx, g.dy, 0); ​​​​​​​​taxiX= g.dx; ​​​​​​​​taxiY= g.dy; ​​​​​​​​return minDist; ​​​​} ​​​​static int[] dirx= {0,1,0,-1}; ​​​​static int[] diry= {1,0,-1,0}; ​​​​static int minDist=Integer.MAX_VALUE; ​​​​static int count=0; ​​​​static void shortestPath(int sx, int sy, int dx, int dy, int depth) {//start x y , destination x y ​​​​​​​​if(depth == minDist) return;//시간단축 ​​​​​​​​if(sx==dx && sy==dy){//목적지 도착하면 갱신 ​​​​​​​​​​​​count++; ​​​​​​​​​​​​minDist = Math.min(minDist,depth); ​​​​​​​​​​​​return; ​​​​​​​​} ​​​​​​​​for(int i=0; i<4; i++){ ​​​​​​​​​​​​int ssx=sx+dirx[i]; ​​​​​​​​​​​​int ssy=sy+diry[i]; ​​​​​​​​​​​​if(ssx>=0 && ssx<N && ssy>=0 && ssy<N && grid[ssy][ssx] != 1 && !visit[ssy][ssx]) {//범위내 & 벽x ​​​​​​​​​​​​​​​​visit[ssy][ssx] = true; ​​​​​​​​​​​​​​​​shortestPath(ssx, ssy, dx, dy, depth + 1); ​​​​​​​​​​​​​​​​visit[ssy][ssx] = false; ​​​​​​​​​​​​} ​​​​​​​​} ​​​​​​​​return; ​​​​} ​​​​static class Guest{ ​​​​​​​​int sx, sy, dx, dy; ​​​​​​​​boolean visit = false; ​​​​​​​​Guest(int sy, int sx, int dy, int dx){ ​​​​​​​​​​​​this.sx= sx; ​​​​​​​​​​​​this.sy=sy; ​​​​​​​​​​​​this.dx=dx; ​​​​​​​​​​​​this.dy=dy; ​​​​​​​​} ​​​​} }

bfs방식으로 푸는것이 맞다고 하니, 아래의 코드는 bfs코드이다.

import java.io.*; import java.util.*; class Node implements Comparable<Node> { int x, y, dist; public Node(int x, int y, int dist) { ‌‌this.x = x; ‌‌this.y = y; ‌‌this.dist = dist; } @Override public int compareTo(Node o) { ‌‌if (this.dist != o.dist) { ‌‌‌return this.dist - o.dist; ‌‌} else { ‌‌‌if (this.x != o.x) { ‌‌‌‌return this.x - o.x; ‌‌‌} else { ‌‌‌‌return this.y - o.y; ‌‌‌} ‌‌} } } class Path { int start_x, start_y, end_x, end_y; public Path(int start_x, int start_y, int end_x, int end_y) { ‌‌this.start_x = start_x; ‌‌this.start_y = start_y; ‌‌this.end_x = end_x; ‌‌this.end_y = end_y; } } public class Main { static int N, M, fuel; static int[][] map; static boolean[][] visited; static int joon_x, joon_y; static int[] dx = { -1, 0, 1, 0 }; static int[] dy = { 0, 1, 0, -1 }; static ArrayList<Node> startList = new ArrayList<>(); static ArrayList<Path> pathList = new ArrayList<>(); 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()); ‌‌fuel = Integer.parseInt(st.nextToken()); ‌‌map = new int[N + 1][N + 1]; ‌‌visited = new boolean[N + 1][N + 1]; ‌‌for (int i = 1; i <= N; i++) { ‌‌‌st = new StringTokenizer(br.readLine()); ‌‌‌for (int j = 1; j <= N; j++) { ‌‌‌‌map[i][j] = Integer.parseInt(st.nextToken()); ‌‌‌‌if (map[i][j] == 1) { ‌‌‌‌‌map[i][j] = -1; ‌‌‌‌} ‌‌‌} ‌‌} ‌‌st = new StringTokenizer(br.readLine()); ‌‌joon_x = Integer.parseInt(st.nextToken()); ‌‌joon_y = Integer.parseInt(st.nextToken()); ‌‌boolean flag = false; ‌‌for (int i = 1; i <= M; i++) { ‌‌‌st = new StringTokenizer(br.readLine()); ‌‌‌int start_x = Integer.parseInt(st.nextToken()); ‌‌‌int start_y = Integer.parseInt(st.nextToken()); ‌‌‌int end_x = Integer.parseInt(st.nextToken()); ‌‌‌int end_y = Integer.parseInt(st.nextToken()); ‌‌‌pathList.add(new Path(start_x, start_y, end_x, end_y)); ‌‌‌map[start_x][start_y] = i; ‌‌} ‌‌while (true) { ‌‌‌if (pathList.size() == 0) { // 모두 데려다줬을 경우 ‌‌‌‌System.out.println(fuel); ‌‌‌‌return; ‌‌‌} ‌‌‌startList.clear(); ‌‌‌visited = new boolean[N + 1][N + 1]; ‌‌‌getStart(joon_x, joon_y); // 출발지 선정 ‌‌‌if (startList.size() == 0) { // 벽에 막힌 경우 ‌‌‌‌System.out.println(-1); ‌‌‌‌return; ‌‌‌} ‌‌‌Node start = startList.get(0); ‌‌‌map[start.x][start.y] = 0; ‌‌‌fuel -= start.dist; ‌‌‌if (fuel < 0) { // 연료 떨어진 경우 ‌‌‌‌System.out.println(-1); ‌‌‌‌return; ‌‌‌} ‌‌‌visited = new boolean[N + 1][N + 1]; ‌‌‌int dist = 0; ‌‌‌for (int i = 0; i < pathList.size(); i++) { // 도착지 선정 ‌‌‌‌Path path = pathList.get(i); ‌‌‌‌if (path.start_x == start.x && path.start_y == start.y) { ‌‌‌‌‌dist = getDist(path.start_x, path.start_y, path.end_x, path.end_y); ‌‌‌‌‌if (dist == -1) { // 벽에 막힌 경우 ‌‌‌‌‌‌System.out.println(-1); ‌‌‌‌‌‌return; ‌‌‌‌‌} ‌‌‌‌‌joon_x = path.end_x; ‌‌‌‌‌joon_y = path.end_y; ‌‌‌‌‌pathList.remove(path); ‌‌‌‌‌break; ‌‌‌‌} ‌‌‌} ‌‌‌fuel -= dist; ‌‌‌if (fuel < 0) { // 연료 떨어진 경우 ‌‌‌‌System.out.println(-1); ‌‌‌‌return; ‌‌‌} ‌‌‌fuel += dist * 2; ‌‌} } public static void getStart(int x, int y) { ‌‌PriorityQueue<Node> q = new PriorityQueue<>(); ‌‌q.add(new Node(x, y, 0)); ‌‌while (!q.isEmpty()) { ‌‌‌Node cur = q.poll(); ‌‌‌if (map[cur.x][cur.y] >= 1) { ‌‌‌‌startList.add(new Node(cur.x, cur.y, cur.dist)); ‌‌‌‌break; ‌‌‌} ‌‌‌for (int i = 0; i < 4; i++) { ‌‌‌‌int nx = cur.x + dx[i]; ‌‌‌‌int ny = cur.y + dy[i]; ‌‌‌‌if (nx > 0 && nx <= N && ny > 0 && ny <= N) { ‌‌‌‌‌if (map[nx][ny] != -1 && !visited[nx][ny]) { ‌‌‌‌‌‌visited[nx][ny] = true; ‌‌‌‌‌‌q.add(new Node(nx, ny, cur.dist + 1)); ‌‌‌‌‌} ‌‌‌‌} ‌‌‌} ‌‌} } public static int getDist(int start_x, int start_y, int end_x, int end_y) { ‌‌Queue<Node> q = new LinkedList<>(); ‌‌q.add(new Node(start_x, start_y, 0)); ‌‌while (!q.isEmpty()) { ‌‌‌Node cur = q.poll(); ‌‌‌if (cur.x == end_x && cur.y == end_y) { ‌‌‌‌return cur.dist; ‌‌‌} ‌‌‌for (int i = 0; i < 4; i++) { ‌‌‌‌int nx = cur.x + dx[i]; ‌‌‌‌int ny = cur.y + dy[i]; ‌‌‌‌if (nx > 0 && nx <= N && ny > 0 && ny <= N) { ‌‌‌‌‌if (map[nx][ny] != -1 && !visited[nx][ny]) { ‌‌‌‌‌‌visited[nx][ny] = true; ‌‌‌‌‌‌q.add(new Node(nx, ny, cur.dist + 1)); ‌‌‌‌‌} ‌‌‌‌} ‌‌‌} ‌‌} ‌‌return -1; } }
반응형

'코딩테스트 > Java' 카테고리의 다른 글

[JAVA] 백준 원판 돌리기  (0) 2021.07.08
[JAVA] 백준 톱니바퀴  (0) 2021.07.06
[JAVA] 백준 청소년 상어  (0) 2021.06.15
[Java] 백준13263 나무자르기  (0) 2021.06.09
비트마스크(Bitmask) : 이진법 이용  (0) 2021.06.03