[백준] 나이트의 이동(java) Bfs

2020-02-26

나이트의 이동 (백준> Dfs_Bfs)

문제 링크

문제설명

체스판 위에 한 나이트가 놓여져 있다. 나이트가 한 번에 이동할 수 있는 칸은 아래 그림에 나와있다. 나이트가 이동하려고 하는 칸이 주어진다. 나이트는 몇 번 움직이면 이 칸으로 이동할 수 있을까?

img

입력

입력의 첫째 줄에는 테스트 케이스의 개수가 주어진다.

각 테스트 케이스는 세 줄로 이루어져 있다. 첫째 줄에는 체스판의 한 변의 길이 l(4 ≤ l ≤ 300)이 주어진다. 체스판의 크기는 l × l이다. 체스판의 각 칸은 두 수의 쌍 {0, …, l-1} × {0, …, l-1}로 나타낼 수 있다. 둘째 줄과 셋째 줄에는 나이트가 현재 있는 칸, 나이트가 이동하려고 하는 칸이 주어진다.

출력

각 테스트 케이스마다 나이트가 몇 번만에 이동할 수 있는지 출력한다.

예제 입력 1 복사

3
8
0 0
7 0
100
0 0
30 50
10
1 1
1 1

예제 출력 1 복사

5
28
0


풀이

package Dfs_Bfs;

import java.util.*;

//40min
public class beak_나이트의이동 {

	static class Pos{
		int x;
		int y;
		int cnt;
		
		Pos(int x,int y,int cnt){
			this.x =x;
			this.y =y;
			this.cnt = cnt;
		}
	}

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		
		int n=sc.nextInt();
		
		for(int i=0;i<n;i++) {
			int m = sc.nextInt();
			int arr[][] = new int[m][m];
			
			sc.nextLine();
			
			Queue<Pos> qu = new LinkedList<>();
			String a[] = sc.nextLine().split(" ");
			qu.add(new Pos(Integer.parseInt(a[0]),Integer.parseInt(a[1]),0));
			arr[Integer.parseInt(a[0])][Integer.parseInt(a[1])] = 1;
			
			String b[] = sc.nextLine().split(" ");
			int endx = Integer.parseInt(b[0]); int endy = Integer.parseInt(b[1]);
			
			while(!qu.isEmpty()) {
				Pos now = qu.poll();
				int nowx = now.x;
				int nowy = now.y;
				
				if(nowx == endx && nowy == endy) {
					System.out.println(now.cnt);
					break;
				}
				
				int dx[] = {-2,-2,-1,-1, 1,1, 2,2};
				int dy[] = {-1, 1,-2, 2,-2,2,-1,1};
				
				for(int j=0; j<8; j++) {
					int nx = nowx + dx[j];
					int ny = nowy + dy[j];
					
					if(nx>=0&&nx<m &&ny>=0&&ny<m && arr[nx][ny]==0){
						arr[nx][ny] = 1;
						qu.add(new Pos(nx,ny,now.cnt+1));
					}
				}
				
			}//while
			
		}
	}
}

후기 (40min)

사방에서 8개로 나뉘었을 뿐 일반 bfs랑 다를거 없는 문제였다!

Read More

[프로그래머스] N으로 표현 (java) Dynamic_programming

2020-02-26

N으로 표현 (프로그래머스> Dynamic_programming)

문제 링크

문제설명

아래와 같이 5와 사칙연산만으로 12를 표현할 수 있습니다.

12 = 5 + 5 + (5 / 5) + (5 / 5) 12 = 55 / 5 + 5 / 5 12 = (55 + 5) / 5

5를 사용한 횟수는 각각 6,5,4 입니다. 그리고 이중 가장 작은 경우는 4입니다. 이처럼 숫자 N과 number가 주어질 때, N과 사칙연산만 사용해서 표현 할 수 있는 방법 중 N 사용횟수의 최솟값을 return 하도록 solution 함수를 작성하세요.

제한사항
  • N은 1 이상 9 이하입니다.
  • number는 1 이상 32,000 이하입니다.
  • 수식에는 괄호와 사칙연산만 가능하며 나누기 연산에서 나머지는 무시합니다.
  • 최솟값이 8보다 크면 -1을 return 합니다.
입출력 예
N number return
5 12 4
2 11 3
입출력 예 설명

예제 #1 문제에 나온 예와 같습니다.

예제 #2 11 = 22 / 2와 같이 2를 3번만 사용하여 표현할 수 있습니다.


풀이

package Dynamic_programming;

import java.util.*;

public class prog_3_N으로표현 {

	static int answer = -1;
	public static void dfs(int n, int number, int cnt, int prev) {
		int temp = n; //

		if(cnt>8) // 8보다 커지면 -1
			return;
		
		if(number == prev) { //숫자가 같을 때
			System.out.println(cnt + " " + answer + " " + prev);
			if(answer == -1 || answer >cnt) //answer가 -1일때 최초로 바뀌는거니까 or answer가 cnt보다 클 떄
				answer = cnt;
			return;
		}
		
		for(int i=0; i<8-cnt; i++) {
			dfs(n,number, cnt+i+1, prev- temp);
			dfs(n,number, cnt+i+1, prev + temp);
			dfs(n,number, cnt+i+1, prev * temp);
			dfs(n,number, cnt+i+1, prev / temp);
			
			temp = temp*10 + n;
		}
		
	}
	
    public static int solution(int N, int number) {
    	
    	dfs(N,number,0,0);
        return answer;
    }
    
    public static void main(String[] args) {
		System.out.println(solution(5,12));
	}
}

후기 (2h)

다시 풀어봐야하는 dp….

Read More

[백준] 토마토2 - Fail(java) Bfs

2020-02-26

토마토2 (백준> Dfs_Bfs)

문제 링크

문제설명

철수의 토마토 농장에서는 토마토를 보관하는 큰 창고를 가지고 있다. 토마토는 아래의 그림과 같이 격자모양 상자의 칸에 하나씩 넣은 다음, 상자들을 수직으로 쌓아 올려서 창고에 보관한다.

img

창고에 보관되는 토마토들 중에는 잘 익은 것도 있지만, 아직 익지 않은 토마토들도 있을 수 있다. 보관 후 하루가 지나면, 익은 토마토들의 인접한 곳에 있는 익지 않은 토마토들은 익은 토마토의 영향을 받아 익게 된다. 하나의 토마토에 인접한 곳은 위, 아래, 왼쪽, 오른쪽, 앞, 뒤 여섯 방향에 있는 토마토를 의미한다. 대각선 방향에 있는 토마토들에게는 영향을 주지 못하며, 토마토가 혼자 저절로 익는 경우는 없다고 가정한다. 철수는 창고에 보관된 토마토들이 며칠이 지나면 다 익게 되는지 그 최소 일수를 알고 싶어 한다.

토마토를 창고에 보관하는 격자모양의 상자들의 크기와 익은 토마토들과 익지 않은 토마토들의 정보가 주어졌을 때, 며칠이 지나면 토마토들이 모두 익는지, 그 최소 일수를 구하는 프로그램을 작성하라. 단, 상자의 일부 칸에는 토마토가 들어있지 않을 수도 있다.

입력

첫 줄에는 상자의 크기를 나타내는 두 정수 M,N과 쌓아올려지는 상자의 수를 나타내는 H가 주어진다. M은 상자의 가로 칸의 수, N은 상자의 세로 칸의 수를 나타낸다. 단, 2 ≤ M ≤ 100, 2 ≤ N ≤ 100, 1 ≤ H ≤ 100 이다. 둘째 줄부터는 가장 밑의 상자부터 가장 위의 상자까지에 저장된 토마토들의 정보가 주어진다. 즉, 둘째 줄부터 N개의 줄에는 하나의 상자에 담긴 토마토의 정보가 주어진다. 각 줄에는 상자 가로줄에 들어있는 토마토들의 상태가 M개의 정수로 주어진다. 정수 1은 익은 토마토, 정수 0 은 익지 않은 토마토, 정수 -1은 토마토가 들어있지 않은 칸을 나타낸다. 이러한 N개의 줄이 H번 반복하여 주어진다.

출력

여러분은 토마토가 모두 익을 때까지 최소 며칠이 걸리는지를 계산해서 출력해야 한다. 만약, 저장될 때부터 모든 토마토가 익어있는 상태이면 0을 출력해야 하고, 토마토가 모두 익지는 못하는 상황이면 -1을 출력해야 한다.

예제 입력 1 복사

5 3 1
0 -1 0 0 0
-1 -1 0 1 1
0 0 0 1 1

예제 출력 1 복사

-1


풀이

package Dfs_Bfs;

import java.util.*;


//1h - half success
class Poos{
	int x;
	int y;
	int z;
	int day;
	
	Poos(int x, int y, int z, int day){
		this.x = x;
		this.y = y;
		this.z = z;
		this.day = day;
	}
	
}

public class beak_토마토2 {
	
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		
		String n[] = sc.nextLine().split(" ");
		
		int y = Integer.parseInt(n[0]); // 열 -> 가로로 y개라는 뜻
		int x = Integer.parseInt(n[1]); // 행 -> 세로로 x개라는 뜻
		int z = Integer.parseInt(n[2]); // 높이
		
		int maze[][][] = new int[z][x][y]; // 맵에 데이터 넣기
		
		Queue<Poos> tomato = new LinkedList<>();
		
		//행개수만큼 넣고 -> 열 -> 높이
		for(int i=0;i<z;i++) {
			for(int j=0;j<x; j++) {
				//한줄씩 받아온거 행에 넣기 ->행 개수만큼
				String a[] = sc.nextLine().split(" ");
				for(int k=0;k<y; k++) {
					maze[i][j][k] =Integer.parseInt(a[k]);
					
					if(maze[i][j][k] == 1)
						tomato.add(new Poos(j,k,i,0));
				}//for - k
			}//for - j
		}//for - i
		
		int realday = 0;
		
		//bfs
		while(!tomato.isEmpty()) {
			Poos nowp = tomato.poll();
			realday = Math.max(realday, nowp.day);
			
			//꺼내서 6방향 살펴서 -> 0이면 1로만들고, tomato에 넣기
			int dx[] = {1,-1,0,0,0,0};
			int dy[] = {0,0,1,-1,0,0};
			int dz[] = {0,0,0,0,1,-1};
			
			for(int i=0; i<6;i++) {
				int nx = nowp.x + dx[i];
				int ny = nowp.y + dy[i];
				int nz = nowp.z + dz[i];
				
				if(nx>=0&&nx<x &&ny>=0&&ny<y &&nz>=0&&nz<z && maze[nz][nx][ny] == 0) {
					maze[nz][nx][ny] = 1; //익혀주고
					tomato.add(new Poos(nx,ny,nz, nowp.day+1));
				}
			}
		}
		
		boolean chk = false;
		
		for(int i=0;i<z;i++) {
			for(int j=0;j<x; j++) {
				for(int k=0;k<y; k++) {
					if(maze[i][j][k] == 0) {
						System.out.println("-1");
						chk=true;
						break;
					}
				}//for - k
			}//for - j
		}//for - i
		
		if(chk == false)
			System.out.println(realday);
		
	}
}

//https://fbtmdwhd33.tistory.com/33

후기 (1h)

분명히 제대로 푼거같은데 예제도 다 맞는데..

왜 어떤 테케가 틀리고 어떤 게 문젠지 알고싶다…퓨ㅠㅠ


tip

  1. 2차원에서 3차원배열을 사용하는 법도 익혀두자

참고링크 : https://fbtmdwhd33.tistory.com/33

Read More

[백준] 크로아티아 알파벳 (java) String

2020-02-25

크로아티아 알파벳 (백준 > String )

문제 링크

문제설명

예전에는 운영체제에서 크로아티아 알파벳을 입력할 수가 없었다. 따라서, 다음과 같이 크로아티아 알파벳을 변경해서 입력했다.

크로아티아 알파벳 변경
č c=
ć c-
dz=
đ d-
lj lj
nj nj
š s=
ž z=

예를 들어, ljes=njak은 크로아티아 알파벳 6개(lj, e, š, nj, a, k)로 이루어져 있다. 단어가 주어졌을 때, 몇 개의 크로아티아 알파벳으로 이루어져 있는지 출력한다.

dž는 무조건 하나의 알파벳으로 쓰이고, d와 ž가 분리된 것으로 보지 않는다. lj와 nj도 마찬가지이다. 위 목록에 없는 알파벳은 한 글자씩 센다.

입력

첫째 줄에 최대 100글자의 단어가 주어진다. 알파벳 소문자와 ‘-‘, ‘=’로만 이루어져 있다.

단어는 크로아티아 알파벳으로 이루어져 있다. 문제 설명의 표에 나와있는 알파벳은 변경된 형태로 입력된다.

출력

입력으로 주어진 단어가 몇 개의 크로아티아 알파벳으로 이루어져 있는지 출력한다.

예제 입력 1 복사

ljes=njak

예제 출력 1 복사

6

예제 입력 2 복사

ddz=z=

예제 출력 2 복사

3


풀이

package String;

import java.util.*;

public class beak_크로아티아알파벳 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		
		String a = sc.next();
		//진짜 너무 바보같다..ㅎ 같은게 있으면 *로 치환하면 그만인 것을...
		
		String words[] = {"c=", "c-", "dz=", "d-", "lj", "nj", "s=", "z="};
		
		for(int i=0;i<words.length; i++) {
			if(a.contains(words[i])) // 들어있는 모든 애들을 replace해준다! 한개만이 아니고!
				a = a.replaceAll(words[i], "*"); // replace()아니고 replaceAll()!!!!!!!!!!!!
				//그리고 치환했으면 반드시 다시 a 문자열에 넣어준다
		}
		
		System.out.println(a.length());
	}
}


후기 (50min)

아… 진짜 이래서 함수를 많이 알고있어야 한다.. 삽질 열심히 하다가, contains 가지고 있을때 -> replaceAll 해주면 한번에 전부 변환 해 줄 수 있었다…ㅠ

문자열 공부도 계속 꾸준히 해두자.. 문자열은 보통 함수로 해결하는 경우가 많으니까!

Read More

[백준] 그룹 단어 체커 (java) String

2020-02-25

그룹 단어 체커 (백준 > String)

문제 링크

문제설명

그룹 단어란 단어에 존재하는 모든 문자에 대해서, 각 문자가 연속해서 나타나는 경우만을 말한다. 예를 들면, ccazzzzbb는 c, a, z, b가 모두 연속해서 나타나고, kin도 k, i, n이 연속해서 나타나기 때문에 그룹 단어이지만, aabbbccb는 b가 떨어져서 나타나기 때문에 그룹 단어가 아니다.

단어 N개를 입력으로 받아 그룹 단어의 개수를 출력하는 프로그램을 작성하시오.

입력

첫째 줄에 단어의 개수 N이 들어온다. N은 100보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에 단어가 들어온다. 단어는 알파벳 소문자로만 되어있고 중복되지 않으며, 길이는 최대 100이다.

출력

첫째 줄에 그룹 단어의 개수를 출력한다.

예제 입력 1 복사

3
happy
new
year

예제 출력 1 복사

3


풀이

package String;

import java.util.*;

public class beak_그룹단어체커 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		
		int n = sc.nextInt();
		int an = 0;
		
		sc.nextLine();
		
		for(int i=0;i<n; i++) {
			int arr[] = new int[26];
			boolean check = false;
			
			String a = sc.nextLine();
			
			for(int j=1; j<a.length(); j++) {
				
				arr[a.charAt(j-1)-'a'] = 1;
				
				if(a.charAt(j) != a.charAt(j-1)) {//나랑 전 단어가 같을 때는 상관 없고!! 나랑 전 단어가 다를 때, 내 전단어는 1표시 돼있고
												 //전 단어는 나랑 다르니까 새로운 내가 이미 전에 나왔었는지 확인해본다 
					if(arr[a.charAt(j)-'a'] !=0)
						check = true;
				}
			}
			
			if(check != true)
				an++;
			
		}//for
		
		System.out.println(an);
		
	}
}


후기 (45min)

엄.. 맞추긴 맞췄는데 아리까리하다! 나와 전 단어가 같을때는 넘어가면서, 동시에 방문했었으니까 1로 체크해준 후,

전 단어와 현재 내가 다른경우에 현재 단어를 전에 사용한적이 있다면 그룹단어가 아닌 것!

Read More