<백준>

- Java


* 거의 최단 경로

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.StringTokenizer;

public class Main {
	
	static int N,M;
	static int S,D;
	static ArrayList<Info>[] map;
	static ArrayList<Integer>[] tracking;
	static boolean[][] isShortest; //true면 a>b가 최단
	static int[] distance;
	static final int INF = Integer.MAX_VALUE;
	
	public static void main(String[] args) throws IOException{
		// TODO Auto-generated method stub
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
		StringTokenizer st;
		
		while(true) {
			st = new StringTokenizer(br.readLine()," ");
			N = Integer.parseInt(st.nextToken());
			M = Integer.parseInt(st.nextToken());
			
			if(N==0 && N==0) break;
			
			st = new StringTokenizer(br.readLine()," ");
			S = Integer.parseInt(st.nextToken());
			D = Integer.parseInt(st.nextToken());
			
			map = new ArrayList[N+1];
			tracking = new ArrayList[N+1];
			distance = new int[N+1];
			isShortest = new boolean[N+1][N+1];
			
			for(int i =0; i<N; i++) {
				map[i] = new ArrayList<>();
			}
			
			int u,v,p;
			for(int i=1; i<=M; i++) {
				st = new StringTokenizer(br.readLine()," ");
				u = Integer.parseInt(st.nextToken());
				v = Integer.parseInt(st.nextToken());
				p = Integer.parseInt(st.nextToken());
				map[u].add(new Info(v,p));
			}
			dijkstra(S);
			if(distance[D]==INF) {
				bw.write("-1"+"\n");
				continue;
			}
			backTracking(D,S);
			dijkstra(S);
			
			if(distance[D]==INF) {
				bw.write("-1"+"\n");
			}else {
				bw.write(distance[D]+"\n");
			}
		
		}
		bw.flush();
		bw.close();
	}
	
	//D에서 S방향으로 tracking을 수행 -> backtracking
	static void backTracking(int now, int end) { //false를 찾아 true로 바꿔줌
		if(now == end) return;
		
		for(int next : tracking[now]) {
			if(isShortest[next][now] == false) {
				isShortest[next][now] =true;
				backTracking(next,end);
			}
		}
	}
	
	static void dijkstra(int s) {
		for(int i =0;i<N; i++) { //다익스트라를 두번 돌릴 예정이라 여기서 초기화해줌
			tracking[i] = new ArrayList<>();
		}
		Arrays.fill(distance,INF);
		
		PriorityQueue<Info> pq = new PriorityQueue<>();
		distance[s]=0; 
		pq.add(new Info(s,0));
		
		while(pq.isEmpty()==false) {
			Info now = pq.poll();
			
			if(now.distance > distance[now.node]){ //더 큰 거리면 패스
				continue;
			}
			
			for(Info next : map[now.node]) {
				if(isShortest[now.node][next.node]==false) {//2번째 다익스트라를 튀함으로 true인경우 pass
					if(distance[next.node]>distance[now.node]+next.distance) { //다음 노드보다 작은 경우
						distance[next.node]=distance[now.node]+next.distance;
						//새로운 distance 이므로 clear 후 add. 
						tracking[next.node].clear(); 
						tracking[next.node].add(now.node);
						pq.add(new Info(next.node, distance[next.node]));
					}else if(distance[next.node]==distance[now.node]+next.distance){
						//모든 최단경우를 tracking에 넣어줘야하기때문에 같은 경우 넣어줌
						tracking[next.node].add(now.node);
					}
				}
			}
		}
		
	}
}

class Info implements Comparable<Info>{
	int node;
	int distance;
	
	public Info(int node, int distance) {
		this.node = node;
		this.distance = distance;
	}
	
	@Override
	public int compareTo(Info o) {
		return Integer.compare(distance,o.distance);
	}
}

 

가장 최단인 경우가 아닌, 거의 최단 경로라 두 번째 짧은걸 찾아야 한다.

따라서 다익스트라를 두번 수행한다.

다익스트라, 백트래킹, 다익스트라.

이렇게 수행하게 된다.

 

백트래킹의 경우는 D-> S 로 가면서, 즉 뒤에서 앞으로 가면서

false인거 발견하면 true로 바꾸고, 재귀로 이를 반복하며 앞으로 가다가,

now가 end가 되면 끝! 이다.

 

다익스트라의 경우는 우선 초기화를 진행한다.

다익스트라를 두 번 진행할 것이기 때문에 먼저 tracking배열을 초기화 해준다.

우선순위 큐를 활용 하기 위해 하나 생성해 준다.

그리고 시작점을 0으로 설정 후 큐에 추가 !

이제 큐가 빌때까지 반복!

최단경우를 tracking에 넣어주는 작업을 수행한다.

 

이제 distance[D] 값이 거의 최단 경로가 되고, 

무한대 값이 아니라면, 출력해준다.

'모각코 > 2022_슈붕팥붕' 카테고리의 다른 글

6회차(01.20) - 목표  (0) 2022.01.20
5회차(01.18) - 결과  (0) 2022.01.19
5회차(01.18) - 목표  (0) 2022.01.18
4회차(01.13) - 결과  (0) 2022.01.13
4회차(01.13) - 목표  (0) 2022.01.13

회의 일자 : 

2022.01.20 20:30 ~ 23:30 

 


목표 : 

-  코딩테스트 대비 (백준)

'모각코 > 2022_슈붕팥붕' 카테고리의 다른 글

6회차(01.20) - 결과  (0) 2022.01.20
5회차(01.18) - 결과  (0) 2022.01.19
5회차(01.18) - 목표  (0) 2022.01.18
4회차(01.13) - 결과  (0) 2022.01.13
4회차(01.13) - 목표  (0) 2022.01.13

<백준>

- Java


* 교수님은 기다리지 않는다

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.StringTokenizer;

public class Main {
	static int N,M;
	static int[] diff;
	static int[] parent;
	
	public static void main(String[] args) throws IOException{
		// TODO Auto-generated method stub
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
		StringTokenizer st;
		while(true) {
			st = new StringTokenizer(br.readLine()," ");	
			N = Integer.parseInt(st.nextToken());
			M = Integer.parseInt(st.nextToken());
			
			if(N==0 && M==0) break;
			
			diff= new int[N+1]; //차이
			parent = new int[N+1]; //무게 잰거 저장
			
			for(int i =0; i<=N; i++) {
				parent[i]=i;
			}
			
			String q;
			int a,b,w;
			
			for(int i=1; i<=M; i++) {
				st = new StringTokenizer(br.readLine()," ");
				q = st.nextToken();
				a = Integer.parseInt(st.nextToken());
				b = Integer.parseInt(st.nextToken());
				if(q.equals("!")) { //상근이가 무게 잼
					w = Integer.parseInt(st.nextToken());
					union(a,b,w);
				}else if(q.equals("?")) { //교수님이 물어보심
					if(find(a)==find(b)) { // 두 샘플 무게 쟀었는지 확인
						bw.write(diff[b]-diff[a]+"\n");
					}else { // 두 샘플 무게 잰적 없으면 차이 구 할 수 없으므로!
						bw.write("UNKNOWN"+"\n");
					}
				}
			}	
		}
		bw.flush();
		bw.close();	
	}
	
	static void union(int a, int b, int w) {
		int parentA = find(a);
		int parentB = find(b);
		//무게차이 갱신
		diff[parentB]=diff[a]-diff[b]+w;
		parent[parentB]=parentA;
	}
	
	static int find(int n) { //부모 갱신하며 n 찾음
		if(parent[n]==n) return n;
		
		int parentIndex = find(parent[n]);
		diff[n]+=diff[parent[n]];
		return parent[n]=parentIndex;
	}
}

 

union - find 문제

 

q(query)에 따라 union과 find를 실행해준다.

 

이때 diff 배열엔 무게 차이를 저장하고, parent 배열엔 부모를 저장한다.

 

q가 ! 이면 상근이가 무게를 재는 경우이므로,

union을 실행하여 무게차이를 갱신해주며 parent 설정해준다.

 

q가 ? 이면 교수가 무게 차이를 묻는 것이기 때문에 

find를 수행해 부모를 갱신하며 찾는다.

find를 통해 찾지못하면 재지 못한 경우로 무게를 차이를 구할 수 없어 unknown을 출력한다.

 

 

'모각코 > 2022_슈붕팥붕' 카테고리의 다른 글

6회차(01.20) - 결과  (0) 2022.01.20
6회차(01.20) - 목표  (0) 2022.01.20
5회차(01.18) - 목표  (0) 2022.01.18
4회차(01.13) - 결과  (0) 2022.01.13
4회차(01.13) - 목표  (0) 2022.01.13

회의 일자 : 

2022.01.18 20:30 ~ 23:30 

 


목표 : 

-  코딩테스트 대비 (백준)

'모각코 > 2022_슈붕팥붕' 카테고리의 다른 글

6회차(01.20) - 목표  (0) 2022.01.20
5회차(01.18) - 결과  (0) 2022.01.19
4회차(01.13) - 결과  (0) 2022.01.13
4회차(01.13) - 목표  (0) 2022.01.13
3회차(01.11) - 결과  (0) 2022.01.11

<프로그래머스 - 깊이/너비 우선 탐색(DFS/BFS)>

- Java


* 단어 변환

class Solution {
    static boolean[] check;
    static int answer;
    public int solution(String begin, String target, String[] words) {
        check = new boolean[words.length];
        dfs(begin,target,words,0);
        return answer;
    }
    static void dfs(String begin, String target, String[] words, int cnt){
        if(begin.equals(target)){
            answer = cnt;
            return;
        }
        for(int i = 0; i<words.length; i++){
            if(check[i]==true) continue; //방문했으면 continue
            //변경 가능한 단어인지 확인
            boolean temp = false;
            for(int j = 0; j<words[i].length(); j++){
                if(begin.charAt(j)!=words[i].charAt(j)){
                    if(temp == true){
                        temp = false;
                        break;
                    }else{
                        temp = true;
                    }
                }
            }
            //dfs
            if(temp==true){
                check[i] = true;
                dfs(words[i],target,words,cnt+1);
                check[i] = false;
            }
        }
        
    }
}

변경 가능한 단어인지 확인해야 한다.

 

난 이 뜻을 이해하는데 오래걸렸다.

왜 문제 이해를 못하냐구요 ,,

쩄든..

한글자만 달라야 바꿀 수 있다.

그니까 자리도 순서대로 다 같고 ,, 딱 한글자만 다른,,

 

따라서 boolean 값을 임의로 하나 잡고(temp) 검사해주었다.

temp가 true인 경우는 바꾸어도 되는 경우니까

그제서야 check[i]를 true로 바꾸고 dfs 호출.

이때 단어는 변환되어가는 것이기 때문에 begin 값에 words[i], 즉 변환할 값을 인자로 넘기고

cnt도 횟수를 나타내는 것으로 증가시키며 인자로 넣는다.

 

그리고 이후 check[i]를 false로 설정해줌으로써 모든 경우의 수를 확인할 수 있도록한다.

 

begin과 target이 같아지면 answer를 cnt 로 설정하고 return.

 

 


* 여행경로

import java.util.ArrayList;
import java.util.Collections;
class Solution {
    static boolean[] check;
    static ArrayList<String> al;
    public String[] solution(String[][] tickets) {
        String[] answer = {};
        check = new boolean[tickets.length];
        al = new ArrayList<>();
        dfs(tickets,"ICN","ICN",0);
        Collections.sort(al);
        answer = al.get(0).split(" ");
        return answer;
    }
    public void dfs(String[][] tickets, String depart, String route, int cnt){
        if(cnt == tickets.length){
            al.add(route);
            return;
        }
        for(int i=0; i<tickets.length; i++){
            if(check[i]==true) continue;
            if(depart.equals(tickets[i][0]) && check[i]==false){
                check[i]= true;
                dfs(tickets,tickets[i][1],route+" "+tickets[i][1],cnt+1);
                check[i]=false;
            }
        }
    }
}

*항상 "ICN"공항에서 출발하므로 dfs 첫 호출시에 인자에 "ICN"을 직접 넣어준다.

앞선 문제와 비슷한 방식.

 

tickets배열에 [a,b] ~~~ 이렇게 있으면 a가 depart인 것들을 찾는다.

이때 check는 false여야 한다.

이 경우에 check를 true로 바꾸고,

dfs호출! 이때 경로를 " "를 경계로하여 string값인 route에 붙여넣어준다.

모든 경우의 수를 위해 false로 바꾼다.

 

이걸 반복하다 cnt가 ticket배열에 길이가 되면, 다 돈 경우이므로

어레이리스트에 넣어준다.

그리고 return.

 

어레이리스트의 정렬은 Collections로 수행

이제 answer 배열에 " "로 split하여 넣어준다.

 

 

'모각코 > 2022_슈붕팥붕' 카테고리의 다른 글

5회차(01.18) - 결과  (0) 2022.01.19
5회차(01.18) - 목표  (0) 2022.01.18
4회차(01.13) - 목표  (0) 2022.01.13
3회차(01.11) - 결과  (0) 2022.01.11
3회차(01.11) - 목표  (0) 2022.01.11

회의 일자 : 

2022.01.13 20:30 ~ 23:30 


목표 : 

-  코딩테스트 대비 (프로그래머스)

'모각코 > 2022_슈붕팥붕' 카테고리의 다른 글

5회차(01.18) - 목표  (0) 2022.01.18
4회차(01.13) - 결과  (0) 2022.01.13
3회차(01.11) - 결과  (0) 2022.01.11
3회차(01.11) - 목표  (0) 2022.01.11
2회차(01.06) - 결과  (0) 2022.01.06

<프로그래머스 - 깊이/너비 우선 탐색(DFS/BFS)>

- Java


* 타겟넘버

class Solution {
    static int answer = 0;
    public int solution(int[] numbers, int target) {
        dfs(numbers,target,0,0);
        return answer;
    }
    
    static void dfs(int[] numbers,int target, int cnt, int sum){
        if(cnt == numbers.length){
            if(sum==target){
                answer++;
            }
            return;
        }
        dfs(numbers,target,cnt+1,sum+numbers[cnt]);
        dfs(numbers,target,cnt+1,sum-numbers[cnt]);
    }
}

각 원소를 조합해서 더하고 뺀 값의 합이 target이 되는 횟수를 리턴하는 문제

 

cnt는 index의 역할을 하며 0부터 numbers.length-1 까지 증가

numbers.length가 되는 순간은 배열을 다 순회한 것이므로 종료되어야 한다.

이때 여태까지의 sum이 target 값과 같다면 answer를 증가시킨다.

dfs안에서 dfs를 호출하며 sum에 numbers[cnt]를 더하고 빼내가며 문제를 해결한다.

 


* 네트워크 

class Solution {
    static boolean[] check;
    public int solution(int n, int[][] computers) {
        int answer = 0;
        check = new boolean[n];
        for(int i=0; i<n; i++){
            if(check[i]==false){
                dfs(computers,i);
                answer++; 
            }
        }
        return answer;
    }
    static void dfs(int[][] computers,int i){
        check[i] = true; 
        for(int j = 0 ; j<computers.length; j++){
            if(i!=j && computers[i][j]==1 && check[j]==false){
                dfs(computers,j);
            }
        }
    }
}

네트워크의 개수를 구하는 문제 

 

연결되어 있는 애들 끼리 하나.

즉, 컴퓨터1, 컴퓨터2, 컴퓨터3 이 있는데,

컴퓨터1과 컴퓨터2가 연결되어 있고, 컴퓨터 3은 연결된 것이 없다면

네트워크는 두 개 인 것이다.

 

n은 컴퓨터의 갯수로 

boolean 배열을 활용해 각 컴퓨터를 검사했는지 check 한다.

따라서 크기는 n

 

반복문을 돌며

검사를 안한 경우에는 dfs를 통해 더 심층적으로 검사해준다.

이때 i를 넘겨주어 i컴퓨터에 대해 검사할 수 있도록 한다. (그니까 .. 음.. 인덱스 넘겨준다구요,, ㅎ ㅎ..)

이때 answer를 여기서 증가시켜준다. 이게 즉 네트워크의 갯수가 된다.

check가 true였다면 이미 검사가 끝난 것이기 때문이다.

만일 다음께 true면 그 이전 컴퓨터가 얘랑 어딘가 연결이 되어서 검사가 끝난 거겠쥬 ,,~?

또한 연결이 된건 네트워크의 개수로 노 인정이니까 ~

 

dfs를 통해서 심층적인 검사를 하게 된다.

우선 check[i] 를 true로 설정해 이 컴퓨터 check함! 을 표시

이때 이 컴퓨터를 i 컴퓨터라고 하겠다. i컴퓨터가 j 컴퓨터와 연결되어있는지 확인할 것이다.

문제의 제한사항에서 computers[i][i]는 항상 1이었다.

따라서 i는 j와 같지 않아야한다.

i!=j 이고 computers[i][j]가 1(연결)일때, 또한 check[j]가 false일때(j 컴퓨터 검사 x)

dfs를 호출하여 연결된 j컴퓨터를 검사한다. 

 

 

'모각코 > 2022_슈붕팥붕' 카테고리의 다른 글

4회차(01.13) - 결과  (0) 2022.01.13
4회차(01.13) - 목표  (0) 2022.01.13
3회차(01.11) - 목표  (0) 2022.01.11
2회차(01.06) - 결과  (0) 2022.01.06
2회차(01.06) - 목표  (0) 2022.01.06

회의 일자 : 

2022.01.11 20:30 ~ 23:30 


목표 : 

-  코딩테스트 대비 (프로그래머스)

'모각코 > 2022_슈붕팥붕' 카테고리의 다른 글

4회차(01.13) - 목표  (0) 2022.01.13
3회차(01.11) - 결과  (0) 2022.01.11
2회차(01.06) - 결과  (0) 2022.01.06
2회차(01.06) - 목표  (0) 2022.01.06
1회차(01.04) - 결과  (0) 2022.01.04

+ Recent posts