2146번: 다리 만들기

여러 섬으로 이루어진 나라가 있다. 이 나라의 대통령은 섬을 잇는 다리를 만들겠다는 공약으로 인기몰이를 해 당선될 수 있었다. 하지만 막상 대통령에 취임하자, 다리를 놓는다는 것이 아깝다

www.acmicpc.net

 


 

 

  • 생각

 

dfs방식으로 풀면 될 것 같다라고 생각한다.

 

dfs방식

1. 모든 섬의 칸을 queue에 넣는다.

2. bfs를 돌린다. (0을 만나면 시작)

3. 섬을 만나면 return하면서 지나온 0의 칸수와 지금까지 가장 짧았던 0의 칸수로 비교
==> 문제가 되는 것은 bfs를 돌면서 같은 섬으로 갈 수 있다는 것

 

 

 

참고)

 

백준 2146 / 다리 만들기 / BFS / JAVA / 골드 3

오늘은 오랜만에 BFS 문제를 풀어보려 한다. 백준 2146번 다리 만들기 문제이다. https://www.acmicpc.net/problem/2146 2146번: 다리 만들기 여러 섬으로 이루어진 나라가 있다. 이 나라의 대통령은 섬을 잇는

devowen.com

이제 문제를 보도록 하자. N X N의 배열이 주어지고 섬이 있는 곳은 1, 없는 곳은 0으로 input 값이 들어온다. 나는 이 값을 받는 inputArr 행렬을 하나 만들고, 각 섬들을 그룹화한 groupArr, 섬으로부터의 거리를 나타낸 distArr 이렇게 세 개의 배열을 만들어서 문제를 풀었다. groupArr는 섬을 한 그룹씩 순서대로 인덱싱을 해서 1,2,3, .. 이런식으로 같은 섬은 같은 숫자를 입력해 주었다. 그리고 distArr는 섬인 경우는 초기값을 0으로 나머지는(섬이 아닌 곳) -1로 해서 구분을 해 주었다. (그림에서 빈 칸은 모두 초기값 0이며 생략했다)

 

 

이렇게 만들고 나서 distArr에서 BFS를 통해 모든 점에 대해 섬에서부터 거리가 얼마나 되는지를 계산한다. 섬 위에 있다면 당연히 그 값은 0이다. 그리고 그 섬에서 인접한 값들은 1이고 그 값에서 인접한 값은 2일 것이다. 그런식으로 -1로 초기에 설정된 점들은 섬들로부터 최단거리를 계산해서 그 값을 넣어 준다.

 

 

이렇게 거리를 계산하다보면 인접한 점의 distArr 배열값이 이미 자연수로 정해진 경우가 있다. 그 경우는 값을 갱신해 주지 않는다. 즉, distArr에서 모든 점을 탐색하고 나면 각각의 점은 섬으로부터의 최단 거리가 되는 것이다. 그렇게 계산을 마치면, distArr에서 임의의 한 점과 그 인접한 점의 합이 최소가 되는 점을 찾는다. 그 값이 최단거리가 되는 것이다.

 

 

물론 BFS로 계산을 하는 것이니, 거리가 1인 점들을 다 찾고 그 다음 거리가 2인 점을 찾을 것이다. 즉 값을 입력하는 순서가 거리 오름차순이라는 의미이다. 따라서 인접한 두 점이 발견되면 바로 그 순간 두 섬 사이의 거리를 계산해서 리턴해 주어도 된다.

 

 

 

  • 코드

 

import java.io.IOException;
import java.io.InputStream;
import java.util.InputMismatchException;
import java.util.LinkedList;
import java.util.Queue;

public class Algorithm {
	static int N, answer, array[][], distanceArray[][], groupArray[][];
	static int[] x = { 0, 0, 1, -1 };
	static int[] y = { 1, -1, 0, 0 };

	public static void main(String[] args) throws Exception {
		SetData();
		bfs();
		System.out.println(answer);
	}

	private static void SetData() throws Exception {
		InputReader in = new InputReader(System.in);

		N = in.nextInt();
		array = new int[N][N];
		distanceArray = new int[N][N];
		groupArray = new int[N][N];
		answer = Integer.MAX_VALUE;

		for (int i = 0; i < N; i++) {
			for (int j = 0; j < N; j++) {
				array[j][i] = in.nextInt();
			}
		}
	}

	private static void bfs() {
		int count = 0;
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < N; j++) {
				if (array[i][j] != 1 || groupArray[i][j] != 0)
					continue; // array가 1이고 g를 초기화 안했다면

				Queue<int[]> queue = new LinkedList<>();
				groupArray[i][j] = ++count; // g를 초기화
				queue.add(new int[] { i, j });
				while (!queue.isEmpty()) {
					int[] location = queue.remove();

					for (int k = 0; k < 4; k++) {
						int r = location[0] + x[k];
						int c = location[1] + y[k];
						if (r < 0 || r >= N || c < 0 || c >= N)
							continue;

						if (array[r][c] == 1 && groupArray[r][c] == 0) {
							queue.add(new int[] { r, c });
							groupArray[r][c] = count;
						}
					}
				}
			}
		}

		Queue<int[]> queue = new LinkedList<>();
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < N; j++) {
				distanceArray[i][j] = -1;
				if (array[i][j] == 1) {
					queue.add(new int[] { i, j });
					distanceArray[i][j] = 0;
				}
			}
		}
		while (!queue.isEmpty()) {
			int[] location = queue.remove();

			for (int k = 0; k < 4; k++) {
				int r = location[0] + x[k];
				int c = location[1] + y[k];

				if (r < 0 || r >= N || c < 0 || c >= N)
					continue;

				if (distanceArray[r][c] == -1) {
					distanceArray[r][c] = distanceArray[location[0]][location[1]] + 1;
					groupArray[r][c] = groupArray[location[0]][location[1]];
					queue.add(new int[] { r, c });
				}
			}
		}

		for (int i = 0; i < N; i++) {
			for (int j = 0; j < N; j++) {
				for (int k = 0; k < 4; k++) {
					int r = i + x[k];
					int c = j + y[k];
					if (r < 0 || r >= N || c < 0 || c >= N)
						continue;

					if (groupArray[i][j] != groupArray[r][c])
						answer = Math.min(answer, distanceArray[i][j] + distanceArray[r][c]);

				}
			}
		}
	}
}

class InputReader {
	private final InputStream stream;
	private final byte[] buf = new byte[8192];
	private int curChar, snumChars;

	public InputReader(InputStream st) {
		this.stream = st;
	}

	public int read() {
		if (snumChars == -1)
			throw new InputMismatchException();
		if (curChar >= snumChars) {
			curChar = 0;
			try {
				snumChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (snumChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int nextInt() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public long nextLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public int[] nextIntArray(int n) {
		int a[] = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		return a;
	}

	public String nextLine() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isEndOfLine(c));
		return res.toString();
	}

	public boolean isSpaceChar(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	private boolean isEndOfLine(int c) {
		return c == '\n' || c == '\r' || c == -1;
	}
}

 

 

14500번: 테트로미노

폴리오미노란 크기가 1×1인 정사각형을 여러 개 이어서 붙인 도형이며, 다음과 같은 조건을 만족해야 한다. 정사각형은 서로 겹치면 안 된다. 도형은 모두 연결되어 있어야 한다. 정사각형의 변

www.acmicpc.net

 

 

 


 

 

 

  • 생각

 

 

dfs 알고리즘을 통해서 모든 모양을 테스트해본다.

 

 

 

  • 코드

 

import java.io.IOException;
import java.io.InputStream;
import java.util.InputMismatchException;

public class Main {
	static int M, N, answer, array [][];

	public static void main(String[] args) throws Exception {
		SetData();
		System.out.println(answer);
	}

	private static void SetData() throws Exception {
		InputReader in = new InputReader(System.in);

		int N = in.nextInt();
		int M = in.nextInt();
		array = new int[M+6][N+6];
		for(int i = 3; i<N+3; i++){
			for(int j = 3; j<M+3; j++){
				array[j][i] = in.nextInt();
			}
		}
		
		for(int i=0; i<M+3; i++){
			for(int j=0; j<N+3; j++){
				dfs(i, j);
			}
		}
	}
	
	private static void dfs(int a, int b){		
		// 직선 (세로 놓기)
		int sum=0;
		sum += array[a][b];
		sum += array[a+1][b];
		sum += array[a+2][b];
		sum += array[a+3][b];
		if(answer<sum){
			answer = sum;
		}
		
		// 직선 (가로 놓기)
		sum=0;
		sum += array[a][b];
		sum += array[a][b+1];
		sum += array[a][b+2];
		sum += array[a][b+3];
		if(answer<sum){
			answer = sum;
		} 
		
		// 네모
		sum=0;
		sum += array[a][b];
		sum += array[a+1][b];
		sum += array[a+1][b+1];
		sum += array[a][b+1];
		if(answer<sum){
			answer = sum;
		}
		// ㄴ  // 왼상단시작 오른 하단 종료. (반시계방향)
		sum=0;
		sum += array[a][b];
		sum += array[a+1][b];
		sum += array[a+2][b];
		sum += array[a+2][b+1];
		if(answer<sum){
			answer = sum;
		}
		// ㄴ case // 왼상단시작 오른 하단 종료. (반시계방향)의 대칭.
		sum=0;
		sum += array[a][b+1];
		sum += array[a+1][b+1];
		sum += array[a+2][b+1];
		sum += array[a+2][b];
		if(answer<sum){
			answer = sum;
		}

		// ㄴ  // 왼하단시작 오른 상단 종료.
		sum=0;
		sum += array[a][b];
		sum += array[a+1][b];
		sum += array[a][b+1];
		sum += array[a][b+2];
		if(answer<sum){
			answer = sum;
		}
		// ㄴ  // 왼하단시작 오른 상단 종료.
		sum=0;
		sum += array[a][b];
		sum += array[a+1][b+2];
		sum += array[a][b+1];
		sum += array[a][b+2];
		if(answer<sum){
			answer = sum;
		}


		// ㄴ  // 왼상단시작 오른 하단 종료 (시계방향) 
		sum=0;
		sum += array[a][b];
		sum += array[a][b+1];
		sum += array[a+1][b+1];
		sum += array[a+2][b+1];
		if(answer<sum){
			answer = sum;
		}
		// ㄴ  // 왼상단시작 오른 하단 종료 (시계방향) 의 대칭
		sum=0;
		sum += array[a][b];
		sum += array[a][b+1];
		sum += array[a+1][b];
		sum += array[a+2][b];
		if(answer<sum){
			answer = sum;
		}
		//  ㄴ  // 오른 상단시작  왼 하단 종료
		sum=0;
		sum += array[a][b+2];
		sum += array[a+1][b+2];
		sum += array[a+1][b+1];
		sum += array[a+1][b];
		if(answer<sum){
			answer = sum;
		}
		// ㄴ  // 오른 상단시작  왼 하단 종료 의 대칭  
		sum=0;
		sum += array[a+1][b+2];
		sum += array[a+1][b+1];
		sum += array[a+1][b];
		sum += array[a][b];
		if(answer<sum){
			answer = sum;
		}
		
		// ㄴㄱ  // 왼상단시작 오른 하단 종료
		sum=0;
		sum += array[a][b];
		sum += array[a+1][b];
		sum += array[a+1][b+1];
		sum += array[a+2][b+1];
		if(answer<sum){
			answer = sum;
		}
		// ㄴㄱ  // 오른 상단시작  하단 종료. 
		sum=0;
		sum += array[a][b+2];
		sum += array[a][b+1];
		sum += array[a+1][b+1];
		sum += array[a+1][b];
		if(answer<sum){
			answer = sum;
		}
		// ㄴㄱ  // 왼하단시작 오른 상단 종료. 
		sum=0;
		sum += array[a+2][b];
		sum += array[a+1][b];
		sum += array[a+1][b+1];
		sum += array[a][b+1];
		if(answer<sum){
			answer = sum;
		}
		// ㄴㄱ  // 왼상단시작 오른 하단 종료.  (ㄱㄴ꼴)
		sum=0;
		sum += array[a][b];
		sum += array[a][b+1];
		sum += array[a+1][b+1];
		sum += array[a+1][b+2];
		if(answer<sum){
			answer = sum;
		}
		// ㅗ   //  ㅜ
		sum=0;
		sum += array[a][b];
		sum += array[a][b+1];
		sum += array[a][b+2];
		sum += array[a+1][b+1];
		if(answer<sum){
			answer = sum;
		}
		// ㅗ   // ㅓ  
		sum=0;
		sum += array[a][b+1];
		sum += array[a+1][b+1];
		sum += array[a+2][b+1];
		sum += array[a+1][b];
		if(answer<sum){
			answer = sum;
		}
		// ㅗ   //  ㅗ  
		sum=0;
		sum += array[a+1][b];
		sum += array[a+1][b+1];
		sum += array[a+1][b+2];
		sum += array[a][b+1];
		if(answer<sum){
			answer = sum;
		}	
		// ㅗ   //  ㅏ  
		sum=0;
		sum += array[a][b];
		sum += array[a+1][b];
		sum += array[a+2][b];
		sum += array[a+1][b+1];
		if(answer<sum){
			answer = sum;
		}


	}
}

class InputReader {
	private final InputStream stream;
	private final byte[] buf = new byte[8192];
	private int curChar, snumChars;

	public InputReader(InputStream st) {
		this.stream = st;
	}

	public int read() {
		if (snumChars == -1)
			throw new InputMismatchException();
		if (curChar >= snumChars) {
			curChar = 0;
			try {
				snumChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (snumChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int nextInt() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public long nextLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public int[] nextIntArray(int n) {
		int a[] = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		return a;
	}

	public String nextLine() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isEndOfLine(c));
		return res.toString();
	}

	public boolean isSpaceChar(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	private boolean isEndOfLine(int c) {
		return c == '\n' || c == '\r' || c == -1;
	}
}

 

 

 

15684번: 사다리 조작

사다리 게임은 N개의 세로선과 M개의 가로선으로 이루어져 있다. 인접한 세로선 사이에는 가로선을 놓을 수 있는데, 각각의 세로선마다 가로선을 놓을 수 있는 위치의 개수는 H이고, 모든 세로선

www.acmicpc.net

 

 


 

 

  • 생각

 

선을 3개 이하로 만들어서 모든 세로 선들이 사라디를 탄 뒤, 자신의 선에 위치하게 만드는 문제이다.

 

dfs방식으로 백트래킹하면서 풀면 될 것 같다. 단, 모두 맞지않으면 -1 출력

 

 

 

  • 코드

 

import java.io.IOException;
import java.io.InputStream;
import java.util.InputMismatchException;

public class Main {
	static int[][] array;
	static int N, M, H, answer;

	public static void main(String[] args) throws Exception {
		SetData();
		System.out.println(answer);
	}

	private static void SetData() throws Exception {
		InputReader in = new InputReader(System.in);

		N = in.nextInt();
		M = in.nextInt();
		H = in.nextInt();
		array = new int[H + 1][N];
		answer = -1;

		for (int i = 0; i < M; i++) {
			int a = in.nextInt() - 1;
			int b = in.nextInt() - 1;
			array[a][b] = 1;
			array[a][b + 1] = -1;
		}

		if (searchOddNumber() > 3)	return;

		for (int i = 0; i <= 3; i++)
			if(dfs(0, 0, 0, i)) break;
	}

	private static boolean dfs(int x, int y, int cnt, int size) {
		if (cnt == size) {
			if (checkLadder()) {
				answer = size;
				return true;
			}
			return false;
		}

		for (int i = x; i < H; i++) {
			for (int j = y; j < N - 1; j++) {
				if (array[i][j] != 0 || array[i][j + 1] != 0)
					continue;

				array[i][j] = 1;
				array[i][j + 1] = -1;
				if (dfs(i, j + 2, cnt + 1, size))
					return true;
				array[i][j] = 0;
				array[i][j + 1] = 0;
			}
			y = 0;
		}
		return false;
	}

	private static boolean checkLadder() {
		for (int j = 0; j < N; j++) {
			int r = 0, c = j;

			while (r <= H) {
				if (array[r][c] == 1)
					c++;
				else if (array[r][c] == -1)
					c--;
				r++;
			}
			if (c != j)
				return false;
		}
		return true;
	}

	private static int searchOddNumber() {
		int oddNumber = 0;
		for (int j = 0; j < N - 1; j++) {
			int num = 0;
			for (int i = 0; i < H; i++)
				if (array[i][j] == 1)
					num++;
			if (num % 2 == 1)
				oddNumber++;
		}
		return oddNumber;
	}
}

class InputReader {
	private final InputStream stream;
	private final byte[] buf = new byte[8192];
	private int curChar, snumChars;

	public InputReader(InputStream st) {
		this.stream = st;
	}

	public int read() {
		if (snumChars == -1)
			throw new InputMismatchException();
		if (curChar >= snumChars) {
			curChar = 0;
			try {
				snumChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (snumChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int nextInt() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public long nextLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public int[] nextIntArray(int n) {
		int a[] = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		return a;
	}

	public String nextLine() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isEndOfLine(c));
		return res.toString();
	}

	public boolean isSpaceChar(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	private boolean isEndOfLine(int c) {
		return c == '\n' || c == '\r' || c == -1;
	}
}

 

 

 

1083번: 소트

크기가 N인 배열 A가 있다. 배열에 있는 모든 수는 서로 다르다. 이 배열을 소트할 때, 연속된 두 개의 원소만 교환할 수 있다. 그리고, 교환은 많아봐야 S번 할 수 있다. 이때, 소트한 결과가 사전

www.acmicpc.net

 

 


 

 

  • 생각

 

1. 앞에서부터 숫자가 작은 경우 S번 만큼 교환?? ==>> 정확하게 정렬되지 않음

 

2. 맨 앞에있는 값 부터 정렬하면 좋다. index 0부터 S까지 확인했는데 index 0보다 큰 경우가 없는 경우는 index 1을 정렬을 해야한다. index 1부터 S+1까지 큰 수가 있으면 가장 큰 수의 index와 가장 큰 수의 index-1과 교환하는 방법을 사용하면 어떨까?? 시간이 괜찮을 까??

 

2번 방법을 사용했는데 시간이 잘 통과가 됐다.

 

 

 

  • 코드

 

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.InputMismatchException;
import java.util.LinkedList;
import java.util.Queue;

public class Algorithm {
	static int N, S;
	static int[] number;
	static StringBuilder sb;

	public static void main(String[] args) throws Exception {
		SetData();
		Sort();
		System.out.println(sb);
	}

	private static void SetData() throws Exception {
		InputReader in = new InputReader(System.in);

		N = in.nextInt();
		number = new int[N];
		sb = new StringBuilder();
		
		for(int i = 0; i < N; i++)
			number[i] = in.nextInt();
		S = in.nextInt();
	}

	private static void Sort() {
		for(int i = 0; i < N; i++) {
			int x = number[i];
			int y = i;
			int temp;
			
			// j-i <= S 해주는 이유 (시간) - j부터 i까지 최대 S번 바꿀 수 있는데 j-i가 S보다 크면 못 바꿈.
			for(int j = i + 1; j < N && j-i <= S; j++) {
				if(x < number[j]) {
					x = number[j];
					y = j;
				}	
			}
			
			// 현재 j-i중에 가장 큰 값을 그 전의 값과 바꿔주는 작업
			for(S -= (y-i); y > i; y--) {
				temp = number[y];
				number[y] = number[y-1];
				number[y-1] = temp;
			}
			
			if(S <= 0) break;		// S 가 0이하이면 바꿀 수 있는게 없으니 반복문 나옴
		}

		for(int i = 0; i < N; i++)
			sb.append(number[i] + " ");
	}
}

class InputReader {
	private final InputStream stream;
	private final byte[] buf = new byte[8192];
	private int curChar, snumChars;

	public InputReader(InputStream st) {
		this.stream = st;
	}

	public int read() {
		if (snumChars == -1)
			throw new InputMismatchException();
		if (curChar >= snumChars) {
			curChar = 0;
			try {
				snumChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (snumChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int nextInt() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public long nextLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public int[] nextIntArray(int n) {
		int a[] = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		return a;
	}

	public String nextLine() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isEndOfLine(c));
		return res.toString();
	}

	public boolean isSpaceChar(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	private boolean isEndOfLine(int c) {
		return c == '\n' || c == '\r' || c == -1;
	}
}

 

2812번: 크게 만들기

N자리 숫자가 주어졌을 때, 여기서 숫자 K개를 지워서 얻을 수 있는 가장 큰 수를 구하는 프로그램을 작성하시오.

www.acmicpc.net

 

 


 

 

 

  • 생각

1. N-K부터 0까지 가장 큰 값을 string으로 더 해준다. 더 해줄 때 K는 +1이 되서 해당 값보다 뒤까지 포함 시킬 수 있게하고 포함된 값은 뒤에 값을 포함할때 포함 못하게 해주면 될 것 같다.  ==>> 시간 초과 

 

2. stack으로 구현.

 

 

stack으로 구현한 코드이다. 앞의 수 부터 push 해주며 stack에 맨 앞의 수가 현재 수보다 작은 경우 pop을 해주며 K값을 1씩 빼준다. 이렇게 해줘야지 앞에 작은 수가 있는 경우 포함되지 않음. 이렇게 push를 해주면 가장 앞에있는 큰 수부터 stack에 남게되는데 문제는 입력한 수가 내림차순으로 되어있는 경우 출력해야되는 수보다 stack에 많이들어가게 된다. 이 경우는 맨앞에서부터 N-K개의 수만큼 출력해주었다.

 

 

재채점 결과 위 코드가 틀렸다고 나와서 stack 부분을 deque로 고쳐 정답을 도출함.

 

 

 

  • 코드

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Stack;
import java.util.StringTokenizer;

public class Main {
	static int N, K;
	static char[] number;

	public static void main(String[] args) throws Exception {
		SetData();
		FindMaxValue();
	}

	private static void SetData() throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());

		N = Integer.parseInt(st.nextToken());
		K = Integer.parseInt(st.nextToken());
		number = br.readLine().toCharArray();
	}

	private static void FindMaxValue() {
		int temp = K;
		Stack<Character> stack = new Stack<Character>();
		for (int i = 0; i < number.length; i++) {
			// 스택의 맨 뒤의 값이 number[i]보다 작으면 삭제한다.
			// 아래 조건을 만족할 때까지 반복.
			while (temp > 0 && !stack.isEmpty() && stack.peek() < number[i]) {
				stack.pop();
				temp--;
			}
			stack.push(number[i]);
		}

		StringBuilder sb = new StringBuilder();
		if (stack.size() <= K) {
			for (int i = 0; i < stack.size(); i++) {
				sb.append(stack.get(i));
			}
		} else {   		// 앞의 수가 커서 pop을 하지 못한 경우
			for(int i = 0; i < N-K;i++) {
				sb.append(stack.get(i));
			}
		}

		System.out.println(sb);
	}
}

 

 

 

  • 수정 코드

 

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.InputMismatchException;
import java.util.LinkedList;
import java.util.Queue;

public class Main {
	static int N, K;
	static char[] number;
	static StringBuilder sb;

	public static void main(String[] args) throws Exception {
		SetData();
		FindMaxValue();
		System.out.println(sb);
	}

	private static void SetData() throws Exception {
		InputReader in = new InputReader(System.in);
		
		N = in.nextInt();
		K = in.nextInt();
		number = in.nextLine().toCharArray();
		sb = new StringBuilder();
	}

	private static void FindMaxValue() {
        Deque<Character> deque = new ArrayDeque<>();
		for (int i = 0; i < number.length; i++) {
			// 스택의 맨 뒤의 값이 number[i]보다 작으면 삭제한다.
			// 아래 조건을 만족할 때까지 반복.
			while (K > 0 && !deque.isEmpty() && deque.getLast() < number[i]) {
        		deque.removeLast();
				K--;
			}
			deque.addLast(number[i]);
		}

	    while(deque.size() > K) {
	       	sb.append(deque.removeFirst());
	    }
	}
}

class InputReader {
	private final InputStream stream;
	private final byte[] buf = new byte[8192];
	private int curChar, snumChars;

	public InputReader(InputStream st) {
		this.stream = st;
	}

	public int read() {
		if (snumChars == -1)
			throw new InputMismatchException();
		if (curChar >= snumChars) {
			curChar = 0;
			try {
				snumChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (snumChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int nextInt() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public long nextLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public int[] nextIntArray(int n) {
		int a[] = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		return a;
	}

	public String nextLine() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isEndOfLine(c));
		return res.toString();
	}

	public boolean isSpaceChar(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	private boolean isEndOfLine(int c) {
		return c == '\n' || c == '\r' || c == -1;
	}
}

 

 

  • 더 좋은 다른 사람코드

 

 

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.InputMismatchException;
import java.util.LinkedList;
import java.util.Queue;

public class Main {
	static int N, K;
	static String number;
	static StringBuilder sb;

	public static void main(String[] args) throws Exception {
		SetData();
		FindMaxValue();
		System.out.println(sb.delete(sb.length() - K, sb.length()));
	}

	private static void SetData() throws Exception {
		InputReader in = new InputReader(System.in);
		
		N = in.nextInt();
		K = in.nextInt();
		number = in.nextLine();
		sb = new StringBuilder();
	}

	private static void FindMaxValue() {
		for (int i = 0; i < N; i++) {
			if (K == 0) {
				sb.append(number.substring(i));
				break;
			}
			char left = number.charAt(i);
			if (left == '9') {
				sb.append(left);
				continue;
			}
			boolean isReduced = false;
			for (int j = i + 1; j < N && j < i + K + 1; j++) {
				char right = number.charAt(j);
				
				if (left < right) {
					K -= j - i;
					i = j - 1;
					isReduced = true;
					break;
				}
			}
			if (!isReduced) {
				sb.append(left);
			}
		}
	}
}

class InputReader {
	private final InputStream stream;
	private final byte[] buf = new byte[8192];
	private int curChar, snumChars;

	public InputReader(InputStream st) {
		this.stream = st;
	}

	public int read() {
		if (snumChars == -1)
			throw new InputMismatchException();
		if (curChar >= snumChars) {
			curChar = 0;
			try {
				snumChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (snumChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int nextInt() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public long nextLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public int[] nextIntArray(int n) {
		int a[] = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		return a;
	}

	public String nextLine() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isEndOfLine(c));
		return res.toString();
	}

	public boolean isSpaceChar(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	private boolean isEndOfLine(int c) {
		return c == '\n' || c == '\r' || c == -1;
	}
}

 

2589번: 보물섬

보물섬 지도를 발견한 후크 선장은 보물을 찾아나섰다. 보물섬 지도는 아래 그림과 같이 직사각형 모양이며 여러 칸으로 나뉘어져 있다. 각 칸은 육지(L)나 바다(W)로 표시되어 있다. 이 지도에서

www.acmicpc.net

 

 


 

  • 생각

 

 

bfs 탐색

탐색을 하며 연결된 array 을 갈 때마다 큐의 사이즈를 재어주어 count 를 늘려줌

 

 

 

 

  • 코드

 

import java.io.IOException;
import java.io.InputStream;
import java.util.InputMismatchException;
import java.util.LinkedList;
import java.util.Queue;

public class Main{
	static int M, N, count, answer;
	static char[][] array;
	static int[] x = { -1, 1, 0, 0 };
	static int[] y = { 0, 0, -1, 1 };
	static boolean[][] check;
	static Queue<int[]> queue;

	public static void main(String[] args) throws Exception {
		SetData();
		System.out.println(answer - 1);
	}

	private static void SetData() throws Exception {
		InputReader in = new InputReader(System.in);
		
		M = in.nextInt();
		N = in.nextInt();

		array = new char[M][N];
		check = new boolean[M][N];
		queue = new LinkedList<>();
		count = 0;
		answer = 0;

		for (int i = 0; i < M; i++) {
			String ss = in.nextLine();
			for (int j = 0; j < N; j++) {
				array[i][j] = ss.charAt(j);
			}
		}
		
		for (int i = 0; i < M; i++) {
			for (int j = 0; j < N; j++) {
				if (array[i][j] == 'L') {

					bfs(i, j);
					check = new boolean[M][N];
				}
				answer = Math.max(count, answer);
				count = 0;
			}
		}
	}

	private static void bfs(int i, int j) {
		queue.offer(new int[] { i, j });

		while (!queue.isEmpty()) {
			int len = queue.size();
			count++;

			for (int l = 0; l < len; l++) {

				int location[] = queue.poll();
				check[location[0]][location[1]] = true;

				for (int direction = 0; direction < 4; direction++) {
					int r = location[0] + x[direction];
					int c = location[1] + y[direction];

					if (r >= 0 && r < M && c >= 0 && c < N) {
						if (!check[r][c] && array[r][c] == 'L') {
							queue.offer(new int[] { r, c });
							check[r][c] = true;
						}
					}
				}
			}
		}
	}
}

class InputReader {
	private final InputStream stream;
	private final byte[] buf = new byte[8192];
	private int curChar, snumChars;

	public InputReader(InputStream st) {
		this.stream = st;
	}

	public int read() {
		if (snumChars == -1)
			throw new InputMismatchException();
		if (curChar >= snumChars) {
			curChar = 0;
			try {
				snumChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (snumChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int nextInt() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public long nextLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public int[] nextIntArray(int n) {
		int a[] = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		return a;
	}

	public String nextLine() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isEndOfLine(c));
		return res.toString();
	}

	public boolean isSpaceChar(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	private boolean isEndOfLine(int c) {
		return c == '\n' || c == '\r' || c == -1;
	}
}

 

 

메모리, 속도 측면에서 훨씬 좋은 코드

 

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class Main{

	static class Obj {
		int y, x, cnt;

		public Obj(int y, int x, int cnt) {
			this.y = y;
			this.x = x;
			this.cnt = cnt;
		}
	}

	static int[] dy = { 1, -1, 0, 0 };
	static int[] dx = { 0, 0, 1, -1 };
	static Queue<Obj> q;
	private static int R;
	private static int C;
	private static int[][] map;
	private static boolean[][] visited;

	public static void main(String[] args) throws Exception {

		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine(), " ");

		R = Integer.parseInt(st.nextToken());
		C = Integer.parseInt(st.nextToken());
		visited = new boolean[R][C];
		map = new int[R][C];
		q = new LinkedList<>();

		for (int i = 0; i < R; i++) {
			String s = br.readLine();
			for (int j = 0; j < C; j++) {
				switch (s.charAt(j)) {
				case 'W':
					map[i][j] = 1;
					break;
				case 'L':
					map[i][j] = 0;
					break;
				}
			}
		}

		int max = 0;
		for (int i = 0; i < R; i++) {
			for (int j = 0; j < C; j++) {
				if (map[i][j] == 0 && !visited[i][j]) {
					visited[i][j] = true;
					q.add(new Obj(i,j,0));
					checkMap(i, j);
					int temp = findWay();
					if (max < temp)
						max = temp;
				}
			}
		}

		System.out.println(max);

	}

	public static int findWay() {
		int max = 0;
		while (!q.isEmpty()) {
			Queue<Obj> q2 = new LinkedList<>();
			Obj temp = q.poll();
			q2.add(temp);
			boolean[][] visited2 = new boolean[R][C];
			while (!q2.isEmpty()) {
				Obj cur = q2.poll();
				visited2[cur.y][cur.x] = true;
				for (int i = 0; i < 4; i++) {
					int ny = cur.y + dy[i];
					int nx = cur.x + dx[i];
					if (ny >= 0 && ny < R && nx >= 0 && nx < C && map[ny][nx] == 0 && !visited2[ny][nx]) {
						visited2[ny][nx] = true;
						q2.add(new Obj(ny, nx, (cur.cnt) + 1));
					}
				}
				if (q2.isEmpty()) {
					if (max < cur.cnt)
						max = cur.cnt;
				}
			}
		}
		
		return max;
	}

	public static void checkMap(int y, int x) {
		boolean check = false;
		for (int i = 0; i < 4; i++) {
			int ny = y + dy[i];
			int nx = x + dx[i];
			if (ny >= 0 && ny < R && nx >= 0 && nx < C && map[ny][nx] == 0 && !visited[ny][nx]) {
				visited[ny][nx] = true;
				check = true;
				checkMap(ny, nx);
			}
		}

		if (!check)
			q.add(new Obj(y, x, 0));
	}

}

 

15918번: 랭퍼든 수열쟁이야!!

세 자연수 n, x, y가 주어진다. (2 ≤ n ≤ 12, 1 ≤ x < y ≤ 2n, 1 ≤ y-x-1 ≤ n)

www.acmicpc.net

 


 

 

  • 생각

 

x, y번째 수가 같다는 것은 x, y번째 수가 모두 y-x+1이라는 것을 의미해서 미리 탐색을 채워주고 시작합시다.

 

backtracking메소드에 index를 증가시키면서 index가 2n이라면 수열을 모두 채운 것이기 때문에 1을 증가시켜 줌. 만약, 인덱스가 아직 채워지지 않았다면, 아직 쓰이지 않은 수 중 삽입 가능한 수 채운 뒤 다음 인덱스부터 재귀적으로 탐색

 

 

  • 코드

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {
	static int[] array, check;
	static int n, x, y,count;

	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());
		x = Integer.parseInt(st.nextToken());
		y = Integer.parseInt(st.nextToken());
		count = 0;
		
		array = new int[25];
		check = new int[25];
		array[x] = array[y] = y - x - 1;
		check[y-x-1] = 1;
		
		BackTracking(1);
		System.out.println(count);
	}

	private static void BackTracking(int index) {
		if(index == 2*n){
			count++; return;
		}
		if(array[index]==0){
			for(int i=1; i<=n; i++){
				if(check[i] == 1) continue;
				if(index+i+1<=2*n && array[index+i+1] == 0){
					array[index] = array[index+i+1] = i;
					check[i] = 1;
					BackTracking(index+1);
					array[index] = array[index+i+1] = check[i] = 0;
				}
			}
		}
	  else BackTracking(index+1);
	}
}

 

9576번: 책 나눠주기

백준이는 방 청소를 하면서 필요 없는 전공 서적을 사람들에게 나눠주려고 한다. 나눠줄 책을 모아보니 총 N권이었다. 책이 너무 많기 때문에 백준이는 책을 구분하기 위해 각각 1부터 N까지의

www.acmicpc.net

 

 


 

 

  • 생각

 

1. 각각의 테스트케이스 별로 a와 b 사이에 있는 책을 줄 수 있으면 주고 아니면 못 준다. array에 배열을 넣은 뒤 정렬 해준 다음 a부터 b까지 보면서 책을 빌려주지 않았으면 빌려주면 될 것 같다. 이걸로 시간 초과가 뜨면 이분탐색?을 써보는 방법도 괜찮을 것 같다.

 

이분 탐색을 하지않아도 a랑 b를 잘 정렬하면 시간초과가 뜨지 않는다. 내가 쓴 정렬 방법은 b를 기준으로 오름차순 정렬하고 b가 같을 땐 a로 오름차순 정렬을해서 책 빌리는 번호가 가장 작은 것 먼저 빌려주게 하였다.

 

 

 

 

  • 코드

 

import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Comparator;
import java.util.InputMismatchException;

public class Main {
	static int testcase, N, M;
	static int[][] book;
	static boolean[] check;
	static StringBuilder sb;	

	public static void main(String[] args) throws Exception {
		SetData();
		System.out.println(sb);
	}

	private static void SetData() throws Exception {
		InputReader in = new InputReader(System.in);
		
		testcase = in.nextInt();
		sb = new StringBuilder();
		
		for(int i = 0; i < testcase; i++) {
			N = in.nextInt();
			M = in.nextInt();
			
			check = new boolean[N];
			book = new int[M][2];
			for(int j = 0; j < M; j++) {
				book[j][0] = in.nextInt();
				book[j][1] = in.nextInt();
			}
			
	        Arrays.sort(book, new Comparator<int[]>() {
	            @Override
	            public int compare(int[] o1, int[] o2) {
	                if(o1[1] != o2[1])	// b 가 같지 않은 경우 b로 오름차순 정렬
	                	return Integer.compare(o1[1], o2[1]);
	                else		// b가 같은 경우 a로 오름차순 정렬
	                	return Integer.compare(o1[0], o2[0]);
	            }
	        });
		
			
			FindMaxValue(); // 각 testcase마다 책을 줄 수 있는 학생의 최대 수를 찾는다.
		}
	}

	private static void FindMaxValue() {
		int count = 0; // 나누어주는 학생의 수를 count
		
		for(int i = 0; i < M; i++) {
			int a = book[i][0];
			int b = book[i][1];

			// 해당하는 범위 내에서
			// 가능한 가장 작은 번호의 책부터 뽑는다.
			for (int j = a-1; j < b; j++) {
				if (!check[j]) {
					check[j] = true;
					count++;
					break;
				}
			}
		}		
		
		sb.append(count + "\n");
	}
}

class InputReader {
	private final InputStream stream;
	private final byte[] buf = new byte[8192];
	private int curChar, snumChars;

	public InputReader(InputStream st) {
		this.stream = st;
	}

	public int read() {
		if (snumChars == -1)
			throw new InputMismatchException();
		if (curChar >= snumChars) {
			curChar = 0;
			try {
				snumChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (snumChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int nextInt() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public long nextLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public int[] nextIntArray(int n) {
		int a[] = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		return a;
	}

	public String nextLine() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isEndOfLine(c));
		return res.toString();
	}

	public boolean isSpaceChar(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	private boolean isEndOfLine(int c) {
		return c == '\n' || c == '\r' || c == -1;
	}
}

+ Recent posts