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;
	}
}

 

17406번: 배열 돌리기 4

크기가 N×M 크기인 배열 A가 있을때, 배열 A의 값은 각 행에 있는 모든 수의 합 중 최솟값을 의미한다. 배열 A가 아래와 같은 경우 1행의 합은 6, 2행의 합은 4, 3행의 합은 15이다. 따라서, 배열 A의

www.acmicpc.net

 

 


 

 

  • 생각

 

배열 N x M 에서 K번 회전 기회가 주어진다.

r, c, s가 주어지면 (r-s, c-s) 부터 (r+s, c+s)까지 직사각형별로 오른쪽으로 한칸씩 돌리면 된다.

돌린 후 각 행의 값을 다 더했을 때 가장 작은 값을 찾는 문제이다.

 

이대로 했는데, 틀렸다. 문제는 K번 index가 주어질 때 순서대로 회전을 시키는 것이 아닌 순서와 상관없이 돌렸을 때 가장 작은 행의 값을 찾는 문제였다.

 

후에 모든 K(r, c, s)의 순서를 바꿔가면서 위의 방법을 반복해서 풀었다.

 

 

 

 

  • 코드

 

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

public class Main {
	static int N, M, K, answer;
	static int[][] array, tempArray, rcs;
	static boolean[] check;
	static int[] x = { -1, 1, 0, 0 };
	static int[] y = { 0, 0, -1, 1 };

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

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

		N = in.nextInt();
		M = in.nextInt();
		K = in.nextInt();
		array = new int[N][M];
		tempArray = new int[N][M];
		answer = Integer.MAX_VALUE;

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

		rcs = new int[K][3];
		for (int i = 0; i < K; i++) {
			rcs[i][0] = in.nextInt() - 1;
			rcs[i][1] = in.nextInt() - 1;
			rcs[i][2] = in.nextInt();
		}
	}

	public static void RotateArray() {
		int[] order = new int[K];
		for(int i = 0; i < K; i++)
			order[i] = i;
		
		while(true) {
			// 여기서 최대값 찾기 ( 회전 연산 ) 
			for (int n : order) {// 회전 순서
				int r = rcs[n][0], c=rcs[n][1], s = rcs[n][2];
				while(s>0) {
					int a = array[r-s][c-s];
					for(int i = r-s; i+1<=r+s;i++) {
						array[i][c-s] = array[i+1][c-s];
					}
					for(int i = c-s;i+1<=c+s;i++) {
						array[r+s][i] = array[r+s][i+1];
					}
					for(int i = r+s;i-1>=r-s;i--) {
						array[i][c+s] = array[i-1][c+s];
					}
					for(int i = c+s; i-1>=c-s;i--) {
						array[r-s][i] = array[r-s][i-1];
					}
					array[r-s][c-s+1] = a;
					if(--s==0)break;
				}
				
			}
			
			// 최소 행 찾기
			for(int i = 0; i<N;i++) {
				int temp = 0; 
				for (int j = 0; j < M; j++) {
					temp+=array[i][j];
				}
				answer = temp<answer?temp:answer;
			}
			
			// 원래 배열로 back
			for (int i = 0; i < N; i++) {
				for (int j = 0; j < M; j++) {
					array[i][j] = tempArray[i][j];
				}
			}
			
			// 순서 바굼
			int f = K-2;
			for (; f>=0  ; f--) {
				if(order[f]<order[f+1])break;
			}
			if(f==-1)break;			
			int l = K-1;
			for(;l>f;l--) {
				if(order[f]<order[l])break;
			}			
			int temp = order[f];
			order[f]= order[l];
			order[l] = temp;
			++f;
			for(int i = K-1;i>f;i--,f++) {
				temp = order[i];
				order[i]= order[f];
				order[f] = temp;
			}
		}
	}
}

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;
	}
}

 

2210번: 숫자판 점프

111111, 111112, 111121, 111211, 111212, 112111, 112121, 121111, 121112, 121211, 121212, 211111, 211121, 212111, 212121 이 가능한 경우들이다.

www.acmicpc.net

 

 


 

 

  • 생각

 

모든 경우의 수를 확인해야 되는 문제이다.

 

dfs 방식

1. 파라미터는 현재 index(a, b), 숫자가 몇개인지(depth), 현재 숫자(number) 이다.

2. basecase는 숫자가 몇개인지를 체크해서 6개가 되고 이전에 없던 숫자이면 answer을 ++하고 return해준다.

3. 체크하는 방법은 boolean으로 1000001개를 만들어 index로 체크한다. (hashset으로 했었는데 더 느리다.)

4. 상, 하, 좌, 우를 돌리면서 (이전 숫자*10 + 현재 숫자), 다음 index, depth를 바꿔주면서 dfs를 돌린다.

 

 

 

  • 코드

 

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

public class Main {
	static int answer;
	static int[][] array;
	static boolean[] check;
	static int[] x = { -1, 1, 0, 0 };
	static int[] y = { 0, 0, -1, 1 };

	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);

		array = new int[5][5];
		check = new boolean[1000001];
		answer = 0;

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

		for (int i = 0; i < 5; i++) {
			for (int j = 0; j < 5; j++) {
				dfs(i, j, 0, array[i][j]);
			}
		}
	}

	public static void dfs(int a, int b, int depth, int number) {
		// basecase
		if (depth == 5) {
			if (!check[number]) {
				check[number] = true;
				answer++;
			}
			return;
		}
		
		// 6번 까지 모든 경우의 수 이동
		for (int i = 0; i < 4; i++) {
			int r = a + x[i];
			int c = b + y[i];

			if (r < 0 || c < 0 || r >= 5 || c >= 5) 	continue;
			dfs(r, c, depth + 1, number * 10 + array[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;
	}
}

 

16637번: 괄호 추가하기

첫째 줄에 수식의 길이 N(1 ≤ N ≤ 19)가 주어진다. 둘째 줄에는 수식이 주어진다. 수식에 포함된 정수는 모두 0보다 크거나 같고, 9보다 작거나 같다. 문자열은 정수로 시작하고, 연산자와 정수가

www.acmicpc.net

 

 


 

 

  • 생각

 

연산은 왼쪽부터 오른쪽으로 순서대로 진행된다. (*, / 연산에 대한 우선순위 없다.)

단, 괄호의 우선순위는 있다. 괄호는 랜덤으로 어디에나 추가될 수가 있다.

 

오래 고민해보니 모든 경우의 수를 훑어야하는 작업일 것 같다라는 생각이 들었다.

고안해낸 방식은 dfs방식이다.

 

 

dfs 방식

1. dfs 파라미터는 연산자인덱스, 현재까지의 합이다. 

2. basecase는 연산기호를 모두 사용했을 때이다. (현재까지의 합이 가장 크다면 업데이트)

3. 괄호가 없는 경우 (연산자의 왼쪽 숫자와 오른쪽 숫자를 연산한 뒤 dfs를 돈다.)

4. 괄호가 있는 경우 (현재 연산자의 바로 뒤 연산자 먼저 연산하고, 현재 연산자를 연산한 뒤 dfs를 돈다.)

 

 

 

  • 코드

 

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

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

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

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

		N = in.nextInt();
		answer = Integer.MIN_VALUE;
		number = new int[N / 2 + 1];
		operator = new char[N / 2];

		String temp = in.nextLine();
		int indexOfNumber = 0;
		int indexOfChar = 0;
		for (int i = 0; i < N; i++) {
			if (i % 2 == 0) {
				number[indexOfNumber++] = Integer.parseInt(temp.charAt(i) + "");
			} else {
				operator[indexOfChar++] = temp.charAt(i);
				;
			}
		}
	}

	public static void dfs(int operatorIndex, int sum) {
		// basecase
		if (operatorIndex >= N / 2) {
			answer = Math.max(answer, sum);
			return;
		}

		// 괄호 안치고 진행하기
		int nobracket = Calculator(operatorIndex, sum, number[operatorIndex + 1]);
		dfs(operatorIndex + 1, nobracket);

		// 더이상 할 작업이 없으면 return
		if (operatorIndex + 1 >= N / 2)
			return;

		// 괄호 치고 진행하기
		int bracket = Calculator(operatorIndex + 1, number[operatorIndex + 1], number[operatorIndex + 2]);
		int result = Calculator(operatorIndex, sum, bracket);
		dfs(operatorIndex + 2, result);

	}

	public static int Calculator(int operatorIndex, int a, int b) {
		switch (operator[operatorIndex]) {
		case '+':
			return a + b;
		case '-':
			return a - b;
		case '*':
			return a * b;
		}
		return 1;
	}
}

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;
	}
}

 

2110번: 공유기 설치

첫째 줄에 집의 개수 N (2 ≤ N ≤ 200,000)과 공유기의 개수 C (2 ≤ C ≤ N)이 하나 이상의 빈 칸을 사이에 두고 주어진다. 둘째 줄부터 N개의 줄에는 집의 좌표를 나타내는 xi (0 ≤ xi ≤ 1,000,000,000)가

www.acmicpc.net

 

 


 

 

  • 생각

1. 단순 O(n^2)으로는 시간 초과가 뜰 것 같다.

 

2. 이분 탐색을 사용해도 될 것 같다. 특정한 간격을 기준으로 가능한 위치에 공유기 설치, 설치 후 공유기 수가 더 설치되야하면 간격을 줄임. 공유기 수를 줄여야 한다면 간격을 늘림.

 

 

 

  • 코드

정답 코드 : 이분탐색을 통해 구현

 

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

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

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

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

		N = in.nextInt();
		C = in.nextInt();

		array = new int[N];
		for (int i = 0; i < N; i++)
			array[i] = in.nextInt();
		Arrays.sort(array);
	}

	private static int SearchBinary() {
		int left = 1;
		int right = array[N - 1] - array[0];
		int d = 0;
		int value = 0;

		while (left <= right) {
			int mid = (left + right) / 2;
			int start = array[0];
			int count = 1;
			for (int i = 0; i < N; i++) { // 집집마다 검색함.
				d = array[i] - start;
				if (d >= mid) { // 만약 첫번째 집과의 거리가 더 크다면 찾았다고 count 올려주고, 내가 찾는집에 이번 집을 넣어준다.
					count++;
					start = array[i];
				}
			}

			if (count >= C) {
				value = mid;
				left = mid + 1;
			} else {
				right = mid - 1;
			}
		}
		return value;
	}
}

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;
	}
}

 

1107번: 리모컨

첫째 줄에 수빈이가 이동하려고 하는 채널 N (0 ≤ N ≤ 500,000)이 주어진다.  둘째 줄에는 고장난 버튼의 개수 M (0 ≤ M ≤ 10)이 주어진다. 고장난 버튼이 있는 경우에는 셋째 줄에는 고장난 버튼

www.acmicpc.net

 

 


 

  • 생각

 

문제는 리모컨을 눌러서 채널 N을 트는 것이다.

 

조건)

1. 처음 시작은 100번이다.

2. 고장난 번호가 있다.

3. 번호를 누르는 것 외로 +,-를 사용할 수 있다.

 

풀이)

1. 처음 시작 채널 100에서 채널 N을 +,-로만 틀 떄의 누르는 횟수를 answer에 저장한다.(Math.abs를 사용하면 편리)

2. 고장난 번호는 boolean 배열을 이용해서 해당 index에 true로 설정해놓는다. (배열의 false index는 사용가능)

3. dfs를 돌린다.

4. basecase는 현재 채널이 채널 N의 길이보다 길어지면 그만 돌린다. (채널 N의 길이보다 +1 을 해줘야한다.)

 **현재 길이보다 +1 해준 이유는 값이 9999이런식으로 가는데 9를 쓰지 못하는 경우 +1을 해주지않으면 8888에서         +로 9999를 만들어야 하는데, +1해주면 10000에서 -한번만 누르면 가능함.

5. basecase에 걸리지 않으면 현재 채널까지 누른 횟수에서 +,-를 사용해서 채널 N을 만들 때의 누른 횟수를 answer로 초기화 시킨다.

6. 반복문으로 채널 0~9번을 누르면서 dfs를 돌린다. (고장난 버튼은 누르지 않음)

 

 

 

  • 코드

 

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

public class Main {
	static int N, answer, limit;
	static boolean[] 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);

		N = in.nextInt();
		array = new boolean[10];
		// 현재 길이보다 +1 해준 이유는 값이 9999이런식으로 가는데 9를 쓰지 못하는 경우 +1을 해주지않으면 8888에서 +로 9999를 만들어야 하는데
		// +1해주면 10000에서 -한번만 누르면 가능함.
		limit = (N+"").length() + 1;

		int numberOfBrokenRemoteControl = in.nextInt();
		for (int i = 0; i < numberOfBrokenRemoteControl; i++)
			array[in.nextInt()] = true;

		// 초기값 100에서 +,-만 사용해서채널 N을 틀 때 누르는 수
		answer = Math.abs(N - 100);
		
		for (int i = 0; i < 10; i++) {
			if (array[i])
				continue;
			
			dfs(i, 1);
		}
	}

	private static void dfs(int value, int count) {
		// basecase (현재 수가 N보다 높아지면 그만 돌린다.)
		if (limit < count)
			return;

		// 현재 누른 횟수와 +,-만 사용해서 채널 N을 틀 때 누르는 수
		answer = Math.min(answer, count + Math.abs(N - value));
		for (int i = 0; i < 10; i++) {
			if (array[i])
				continue;
			
			dfs((value * 10) + i, count + 1);
		}
	}
}

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;
	}
}

 

 

 

  • 다른 사람 코드

가져온 이유) 내 코드보다 시간이 5배 정도 빠르다. 공부해볼 필요가 있다.

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

public class Main {

    public static void main(String[] args) throws NumberFormatException, IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        int m = Integer.parseInt(br.readLine());
        int ret = (n > 100)? n - 100 : 100 - n;
        boolean[] isBrokenButton;
        StringTokenizer st;
        
        if(m == 0) {
            System.out.print((String.valueOf(n).length() < ret)? String.valueOf(n).length() : ret);
            return;
        }
        
        st = new StringTokenizer(br.readLine());
        isBrokenButton = new boolean[10];
        
        if(n == 100) {
            System.out.print(0);
            return;
        } else if(m == 10) {
            System.out.print(ret);
            return;
        }
        
        while(st.hasMoreTokens())
            isBrokenButton[Integer.parseInt(st.nextToken())] = true;

        System.out.print(getPushCountOfButtonsToMoveChannel(n, isBrokenButton));
    }
    
    private static int getPushCountOfButtonsToMoveChannel(int destChannel, boolean[] isBrokenButton) {
        int ret = (destChannel > 100)? destChannel - 100 : 100 - destChannel;
        int lowChannel = -1, highChannel = -1, maxChannel = 100;
        int divider = (destChannel > 0)? ((int) Math.pow(10, (int) Math.log10(destChannel))) : 1;
        boolean isBrokenDestChannel = false;

        for(int i = divider; i > 0; i /= 10) {
            if(isBrokenButton[destChannel / i % 10]) {
                isBrokenDestChannel = true;
                break;
            }
        }
        
        if(!isBrokenDestChannel) {
            int retOfDestChannel = String.valueOf(destChannel).length();
            return (retOfDestChannel < ret)? retOfDestChannel : ret;
        }
        
        for(int i = 0; i < (int) Math.log10(destChannel); i++)
            maxChannel *= 10;
        
        for(int i = destChannel - 1; i >= 0; i--) {
            boolean isBrokenLowChannel = false;
            int brokenDivider = 0;
            
            divider = (i > 0)? ((int) Math.pow(10, (int) Math.log10(i))) : 1;
            
            for(int j = divider; j > 0; j /= 10) {
                if(isBrokenButton[i / j % 10]) {
                    isBrokenLowChannel = true;
                    brokenDivider = j;
                    break;
                }
            }

            if(isBrokenLowChannel) {
                i -= i % brokenDivider;
            } else {
                lowChannel = i;
                break;
            }
        }

        for(int i = destChannel + 1; i < maxChannel; i++) {
            boolean isBrokenHighChannel = false;
            int brokenDivider = 0;
            
            divider = (i > 0)? ((int) Math.pow(10, (int) Math.log10(i))) : 1;
            
            for(int j = divider; j > 0; j /= 10) {
                if(isBrokenButton[i / j % 10]) {
                    isBrokenHighChannel = true;
                    brokenDivider = j;
                    break;
                }
            }

            if(isBrokenHighChannel) {
                i -= i % brokenDivider;
                i += brokenDivider - 1;
            } else {
                highChannel = i;
                break;
            }
        }
        
        if(lowChannel > -1) {
            int retOfLowChannel = String.valueOf(lowChannel).length();
            
            retOfLowChannel += destChannel - lowChannel;
            ret = (retOfLowChannel < ret)? retOfLowChannel : ret;
        }

        if(highChannel > -1) {
            int retOfHighChannel = String.valueOf(highChannel).length();
            
            retOfHighChannel += highChannel - destChannel;
            ret = (retOfHighChannel < ret)? retOfHighChannel : ret;
        }
        
        return ret;
    }
    
}

+ Recent posts