1525번: 퍼즐

세 줄에 걸쳐서 표에 채워져 있는 아홉 개의 수가 주어진다. 한 줄에 세 개의 수가 주어지며, 빈 칸은 0으로 나타낸다.

www.acmicpc.net

 

 

 

 


 

 

 

 

  • 생각

 

입력한 배열에서 0인 곳이 비어있는 곳인데 비어있는 곳에서 상, 하, 좌, 우로 한번씩 움직이면서

1 2 3

4 5 6

7 8 0

 

처럼 출력이 나오게 만들면 되는 문제이다. (단, 만들지 못할시 -1 출력)

 

푼 방식은 bfs 방식이다.

 

배열로 입력을 받으려 했는데 문제가 많았다. (메모리, 시간문제)

 

변경한 방법은 정수형으로 받아서 hashSet을 사용했다.

hashSet에 지나온 정수형을 모두 추가한다. (ex, 123456789, 312456897) 0이 없는 이유는 01234568로 추가를 하면 1234568로 추가가 되기 때문에 0을 9로 바꾸어 주었다.

 

위치를 바꿀 수 있는 것은 9의 위치이기 때문에 해당 위치를 찾고 상, 하, 좌, 우 중에서 움직일 수 있는 곳으로 움직인다. (단, hashSet에 추가되어있는 것들은 이미 지나와서 123456789를 만들거나 만들지 못했던 것들이기 때문에 건너띄어준다.)

 

 

 

 

  • 코드

 

import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.HashSet;
import java.util.InputMismatchException;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;

public class Main {
	static int[] x = { -1, 1, 0, 0 };
	static int[] y = { 0, 0, -1, 1 };
	static int answer, count;
	static Set<Integer> check;
	static Queue<int[]> queue;

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

		answer = Integer.MAX_VALUE;
		count = 0;
		check = new HashSet<Integer>();
		queue = new LinkedList<>();
		int temp = 0, input = 0;

		for (int i = 0; i < 3; i++) {
			for (int j = 0; j < 3; j++) {
				input = in.nextInt();
				if (input == 0)
					input = 9;
				temp = temp * 10 + input;
			}
		}

		check.add(temp);
		queue.offer(new int[] {temp, 0});

		bfs();
		
		if(answer == Integer.MAX_VALUE) answer = -1;
	}

	private static void bfs() {
		int nowNumber[], nowIndex, nowRow, nowColumn, nextNumber;
		String nowString;
		while (!queue.isEmpty()) {
			nowNumber = queue.poll();
			if (nowNumber[0] == 123456789)
				answer = Math.min(answer, nowNumber[1]);

			nowString = String.valueOf(nowNumber[0]);
			nowIndex = nowString.indexOf('9');
			nowRow = nowIndex / 3;
			nowColumn = nowIndex % 3;

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

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

				int nextIndex = r * 3 + c;	// 이동할 index

				StringBuilder next = new StringBuilder(nowString);
				char temp = next.charAt(nextIndex);
				next.setCharAt(nextIndex, '9');
				next.setCharAt(nowIndex, temp);
				nextNumber = Integer.parseInt(next.toString());	//이동한 값
				
				if(check.contains(nextNumber)) continue;
				
				count++;
				check.add(nextNumber);
				queue.offer(new int[] {nextNumber, nowNumber[1] + 1});
				count--;
			}

		}
	}
}

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

 

1963번: 소수 경로

소수를 유난히도 좋아하는 창영이는 게임 아이디 비밀번호를 4자리 ‘소수’로 정해놓았다. 어느 날 창영이는 친한 친구와 대화를 나누었는데: “이제 슬슬 비번 바꿀 때도 됐잖아” “응 지금

www.acmicpc.net

 

 

 


 

 

 

  • 생각

 

testcase만큼 4자리인 왼쪽 수를 오른쪽 수로 한자리씩 소수로만 만들면서 변경해야한다.

 

dfs방식으로 basecase를 왼쪽 수와 오른쪽 수가 같아질때로 만든 뒤 한자리씩 소수로만 변경하면서 돌리면 어떨까??

- 4자리의 숫자를 한개씩 바꾸며 재귀방식으로 구현하면 4자리의 수에서 한개를 골라 변경한다. (이 때 변경한 수는 소수) basecase는 첫번째 입력한 수와 두번째 입력이 같을 때

==>> 무한루프에 빠진다. 이유는 첫번째 수가 두번째 수로 가지 못할 확률이 있는데 그 부분에서 basecase처리를 못해서 계속 재귀에 빠지게 된다.

 

bfs방식으로 해서 queue가 다 돌았는데 첫번째 수가 두번째 수로 가지못할 때 Impossible을 출력해주는 방향으로 가면 위의 재귀처럼 무한루프에 빠지지 않을 것 같다.

 

 

 

  • 코드

 

 

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

public class Main {
	static boolean[] primes;
	static Queue<int[]> queue;
	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);

		sb = new StringBuilder();

		int testcase = in.nextInt();
		primes = new boolean[10000];
		
		for (int i = 0; i < testcase; i++) {
			Arrays.fill(primes, false);
			bfs(in.nextInt(), in.nextInt());
		}
	}

	private static void bfs(int preNumber, int postNumber) {
		queue = new LinkedList<>();
		queue.add(new int[] { preNumber, 0 });
		if (preNumber == postNumber) {
			sb.append(0).append("\n");
			return;
		}
		while (!queue.isEmpty()) {
			int[] primeRoot = queue.poll();
			if (!primes[primeRoot[0]]) {
				// 지나온건 다시 안돌아가도록
				primes[primeRoot[0]] = true;
				
				char[] numbers = Integer.toString(primeRoot[0]).toCharArray();

				for (int i = 0; i <= 9; i++) {
					for (int j = 0; j < 4; j++) {
						if (j == 0 && i == 0)   continue;
						
						char temp = numbers[j];
						numbers[j] = (char) (i + '0');
						int changedPrimeNumber = Integer.parseInt(String.valueOf(numbers));
						numbers[j] = temp;
						if (primes[changedPrimeNumber])		continue;
						if (check(changedPrimeNumber)) {
							if (changedPrimeNumber == postNumber) {
								sb.append(primeRoot[1] + 1).append("\n");
								return;
							}
							queue.add(new int[] { changedPrimeNumber, primeRoot[1] + 1 });
						}
					}
				}
			}
		}
		sb.append("Impossible").append("\n");
	}

	private static boolean check(int number) {
		for (int i = 2; i <= (int) Math.sqrt(number); i++) {
			if (number % i == 0)
				return false;
		}
		return 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.FileInputStream;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {
	private static boolean[] primeTable = new boolean[10000];
	private static int[] bfsTable = new int[10000];
	private static final int MAX = 10000;
	private static final String IMPOSSIBLE = "Impossible";
	
	private static int T;
	private static StringBuffer answer;
	
	public static void main(String[] args) throws Exception {
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st;
		answer = new StringBuffer();
		findPrime();
		
		T = Integer.parseInt(in.readLine());
		
		for (int tc = 1 ; tc <= T ; tc++) {
			st = new StringTokenizer(in.readLine());
			int startPrime = Integer.parseInt(st.nextToken());
			int endPrime = Integer.parseInt(st.nextToken());
			initBfsTable();
			int a = findAnswer(startPrime, endPrime);
			if (a < 0) {
				answer.append(IMPOSSIBLE);
			}
			else {
				answer.append(a);
			}
			answer.append("\n");
		}
		System.out.println(answer.toString());
	}
	private static void findPrime() {
		primeTable[0] = false;
		primeTable[1] = false;
		for (int i = 2 ; i <= 9999 ; i++) {
			primeTable[i] = true;
		}
		
		for (int i = 2 ; i <= 9999 ; i++) {
			if (primeTable[i] == true) {
				for (int j = i * 2 ; j <= 9999 ; j += i) {
					primeTable[j] = false;
				}
			}
		}
	}
	
	private static void initBfsTable() {
		for (int i = 1000 ; i <= 9999 ; i++) {
			bfsTable[i] = (primeTable[i]) ? MAX : -1;
		}
	}
	
	private static int findAnswer(int startPrime, int endPrime) {
		int step = 0;
		boolean findflag = false;
		int currP = startPrime;
		
		int[] stack1 = new int[9000];
		int sp1 = 0;
		int[] stack2 = new int[9000];
		int sp2 = 0;
		
		int[] currStack = stack1;
		int currsp = sp1;
		int[] nextStack = stack2;
		int nextsp = sp2;
		
		currStack[currsp++] = startPrime;
		bfsTable[startPrime] = 0;
		
		if (startPrime == endPrime) {
			return 0;
		}
		
		do {
			step++;
			int seed;
			int nextP;
			findflag = false;
			for (int s = 0 ; s < currsp ; s++) {
				currP = currStack[s];
				// 1000 pos
				seed = currP % 1000;
				for (int i = 1 ; i <= 9 ; i++) {
					nextP = i * 1000 + seed;
					if (bfsTable[nextP] > step) {
						bfsTable[nextP] = step;
						findflag = true;
						nextStack[nextsp++] = nextP;
					}
				}

				// 100 pos
				seed = (currP / 1000) * 1000 + currP % 100;
				for (int i = 0 ; i <= 9 ; i++) {
					nextP = i * 100 + seed;
					if (bfsTable[nextP] > step) {
						bfsTable[nextP] = step;
						findflag = true;
						nextStack[nextsp++] = nextP;
					}
				}

				// 10 pos
				seed = (currP / 100) * 100 + currP % 10;
				for (int i = 0 ; i <= 9 ; i++) {
					nextP = i * 10 + seed;
					if (bfsTable[nextP] > step) {
						bfsTable[nextP] = step;
						findflag = true;
						nextStack[nextsp++] = nextP;
					}
				}

				// 1 pos
				seed = (currP / 10) * 10;
				for (int i = 0 ; i <= 9 ; i++) {
					nextP = i + seed;
					if (bfsTable[nextP] > step) {
						bfsTable[nextP] = step;
						findflag = true;
						nextStack[nextsp++] = nextP;
					}
				}
			}
			
			// exchange stack;
			int[] tempStack = currStack;
			currStack = nextStack;
			nextStack = tempStack;
			currsp = nextsp;
			nextsp = 0;
			
		} while(findflag && bfsTable[endPrime] == MAX);
		
		if (!findflag) {
			return -1;
		}
		
		return step;
	}
}

 

2666번: 벽장문의 이동

첫 번째 줄에 벽장의 개수를 나타내는 3보다 크고 20보다 작거나 같은 하나의 정수, 두 번째 줄에 초기에 열려있는 두 개의 벽장을 나타내는 두 개의 정수, 그리고 세 번째 줄에는 사용할 벽장들

www.acmicpc.net

 

 

 


 

 

 

  • 생각

 

N개의 벽장에서 N-2개의 벽장만 문이 닫혀있고 2개는 문이 열려있다.

 

벽장문의 이동 횟수와, 이동 순서가 주어지는데 해당 이동순서대로 벽장을 이동했을 때 최소로 이동할 수 있는 값을 찾으면 된다.

 

벽장문이 이동하는 경우의 수는 왼쪽, 오른쪽 2가지이다.

해당 문제는 읽어보면 알겠지만 모든 경우의 수를 돌아봐야하는 브루트포스 문제이다.

 

나는 dfs 방식을 선택했다.

 

dfs 방식

- basecase는 모든 index를 돌아서 index가 이동 횟수를 넘었을 때

- 추가적으로 현재 count가 지금까지 모든 경우의 수를 돌았던 count보다 낮을 시 작업을 더이상 하지않는다.

- basecase로 걸러지지 않았을 땐, 왼쪽 오른쪽 모든 경우의수를 돌았다. (왼쪽, 오른쪽을 쉽게 구하기 위해 파라미터로 문이 없는 벽장의 index를 포함시킨다.)

 

쉽게 구하기 위해

- Math.abs을 활용 했다. (Math.abs는 절대값을 씌워주는 함수이다.)

 

 

 

  • 코드

 

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

public class Main {
	static int answer, move, cupboard;
	static int[] moves;

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

		answer = Integer.MAX_VALUE;
		cupboard = in.nextInt();
		int first = in.nextInt();
		int second = in.nextInt();
		
		move = in.nextInt();
		moves = new int[move];
		
		for(int i = 0; i < move; i++) {
			moves[i] = in.nextInt();
		}
		
		dfs(first, second, 0, 0);
	}
	 
	private static void dfs(int first, int second, int index, int count) {
	    // 분기한정
	    if (count > answer) return;
	 
	    // basecase
	    if (index >= move) {
	        answer = Math.min(answer, count);
	        return;
	    }
	    
	    // left
	    dfs(moves[index], second, index + 1, count + Math.abs(first - moves[index]));
	    // right
	    dfs(first, moves[index], index + 1, count + Math.abs(second - moves[index]));
	}
}

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

 

2312번: 수 복원하기

첫째 줄에 테스트 케이스의 수가 주어진다. 각 테스트 케이스마다 양의 정수 N (2 ≤ N ≤ 100,000)이 주어진다.

www.acmicpc.net

 

 

 


 

 

 

 

  • 생각

 

미리 소수인 수를 정수 배열에 넣은 다음 count 배열을 통해 해당 소수를 몇번 사용하는지를 통해 소인수 분해를 진행한다.

 

 

 

  • 코드

 

 

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

public class Main {
	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);

		sb = new StringBuilder();
		int N = in.nextInt();

		int[] primes = {
				2 ,   3,    5 ,   7  ,  11 ,   13 ,   17 ,   19 ,   23  ,  29,
				31 ,   37  ,  41   , 43 ,   47 ,   53 ,  59   ,61   , 67  ,  71,
				73  ,  79  ,  83  ,  89  ,  97  ,  101 ,   103   , 107 ,   109  ,  113,
				127  ,  131  ,  137   , 139   , 149 ,   151 ,   157 ,   163,    167 ,   173,
				179  ,  181   , 191  ,  193  ,  197  ,  199  ,  211 ,   223 ,   227   , 229,
				233   , 239 ,   241   , 251 ,   257 ,   263 ,   269  ,  271  ,  277   , 281,
				283    ,293  ,  307  ,  311  ,  313  ,  317   
		};
		int[] count = new int[66];
		
		for (int i = 0; i < N; i++) {
			int number = in.nextInt();
			for (int j = 0; j < 66; j++) {
				while (number % primes[j] == 0) {
					number /= primes[j];
					count[j]++;
				}
			}
			for (int c = 0; c < 66; c++) {
				if (count[c] != 0) {
					sb.append(Integer.toString(primes[c]) + " " + Integer.toString(count[c]) + "\n");
					count[c] = 0;
				}
			}
			if (number != 1) sb.append(Integer.toString(number) + " 1\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;
	}
}

 

9421번: 소수상근수

양의 정수 n의 각 자리수의 제곱의 합을 계산한다. 그렇게 해서 나온 합도 각 자리수의 제곱의 합을 계산한다. 이렇게 반복해서 1이 나온다면, n을 상근수라고 한다. 700은 상근수이다. 72 + 02 + 02 =

www.acmicpc.net

 

 

 


 

 

  • 생각

 

 

처음 에라토스테네스의 체 방법으로 소수를 구한 뒤 소수중에서 재귀를 통해 상근수를 찾는다. 

 

 

  • 코드

 

 

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

public class Main {
	static boolean[] prime, flag, number;
	static StringBuilder sb;
	static int N;

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

		prime = new boolean[1000001];
		flag = new boolean[1000001];
		number = new boolean[1000001];
		sb = new StringBuilder();
		N = in.nextInt();

		getPrimeNumber();
		getSangGeunSoo(N);

		for (int i = 1; i <= N; i++) {
			if (getSangGeunSoo(i) && !prime[i]) {
				sb.append(i).append("\n");
			}
		}
	}

	public static boolean getSangGeunSoo(int index) {
		// basecase
		if (index == 1)	return true;
		
		if (flag[index])  return number[index];
		
		flag[index] = true;

		int sum = 0, div = 1000001, cur = index;

		while (cur > 0) {
			int temp = cur / div;
			sum += Math.pow(temp, 2);
			cur %= div;
			div /= 10;
		}
		return number[index] = getSangGeunSoo(sum);

	}

	private static void getPrimeNumber() {
		prime[0] = prime[1] = true;
		for (int i = 2; i <= 1000000; i++) {
			// true면 이미 소수이므로 pass
			if (prime[i]) {
				continue;
			}

			// 해당 수로 나누어 떨어지는 수는 소수이므로 true로 check
			for (int j = i + i; j <= 1000000; j += i) {
				prime[j] = 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;
	}
}

 

17136번: 색종이 붙이기

<그림 1>과 같이 정사각형 모양을 한 다섯 종류의 색종이가 있다. 색종이의 크기는 1×1, 2×2, 3×3, 4×4, 5×5로 총 다섯 종류가 있으며, 각 종류의 색종이는 5개씩 가지고 있다. <그림 1> 색종이를 크

www.acmicpc.net

 

 

 


 

 

 

  • 생각

1x1. 2x2. 3x3, 4x4, 5x5 색종이로 10x10 사각형의 1인 부분을 최소의 색종이로 덮을 수 있는 수를 찾는 문제이다.

완벽한 정확도를 위해 모든 경우의 수를 돌리는 브루트포스 알고리즘으로 풀어야 겠다고 생각했다.

 

가장 큰 색종이부터 덮고 다시 덮은 부분을 되돌리면서 모든 경우의 수를 돌려보았다. (같은 크기의 색종이를 5번 이상 사용하면 안된다.)

 

 

 

 

 

  • 코드

 

 

 

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

public class Main {
	static int[][] array;
	static int[] check;
	static int 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);

		array = new int[10][10];
		check = new int[5];
		answer = Integer.MAX_VALUE;
		
		for(int i = 0; i < 10; i++) {
			for(int j = 0; j < 10; j++) {
				array[i][j] = in.nextInt();
			}
		}
		
		dfs(0);
		if(answer == Integer.MAX_VALUE)
			answer = -1;
	}

	private static void dfs(int y) {
        if(CheckSuccess()) {
            int count = 0;
            for(int i = 0 ; i < 5 ; i++) {
                count += check[i];
            }
            if(answer > count)
                answer = count;
            return;
        }
 
        for(int i = y ; i < 10 ; i++) {
            for(int j = 0 ; j < 10 ; j++) {
                if(array[i][j] == 1) {
                    for(int Size = 4 ; Size >=0 ; Size--) {
                        if(check[Size] < 5 && CheckSquare(i, j, Size)) {
                            check[Size]++;
                            CoverSquare(i, j, Size);
                            dfs(i);
                            UncoverSquare(i, j, Size);
                            check[Size]--;
                        }
                    }
                    return;
                }
            }
        }
	}
	
	private static boolean CheckSquare(int y, int x, int Size) {
		// 규격을 벗어나는 경우
		if(x + Size >= 10 || y + Size >= 10) return false;
		
        for(int i = y ; i <= Size + y ; i++) {
            for(int j = x ; j <= Size + x; j++) {
                if(array[i][j] == 0)
                    return false;
            }
        }
        return true;
	}
	
	private static void CoverSquare(int y, int x, int Size) {	
        for(int i = y ; i <= Size + y ; i++) {
            for(int j = x ; j <= Size + x; j++) {
                array[i][j] = 0;
            }
        }
	}
	
	private static void UncoverSquare(int y, int x, int Size) {		
        for(int i = y ; i <= Size + y ; i++) {
            for(int j = x ; j <= Size + x; j++) {
                array[i][j] = 1;
            }
        }
	}
	
    private static boolean CheckSuccess() {
        for(int i = 0 ; i < 10 ; i++) {
            for(int j = 0 ; j < 10 ; j++) {
                if(array[i][j] == 1)
                    return false;
            }
        }
        return 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.IOException;
import java.io.InputStream;
import java.util.InputMismatchException;

public class Main {
	static int[][] map;
	static int[][] msize;
	static boolean[][] cover;
	static int[][] visit;
	static int[] paper;
	static int count;
	static int 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);

		map = new int[10][10];
		msize = new int[10][10];
		visit = new int[10][10];
		cover = new boolean[10][10];
		paper = new int[6];
		answer = Integer.MAX_VALUE;
		
		for(int i = 0; i < 10; i++) {
			for(int j = 0; j < 10; j++) {
				map[i][j] = in.nextInt();
			}
		}
		
		for(int i = 0; i < 10; i++) {
			for(int j = 0; j < 10; j++) {
				if(map[i][j] == 1) {
					int count = 1;
					loop:for(int k = 1; k <= 4; k++) {
						for(int i2 = i; i2 <= i+k; i2++) {
							for(int j2 = j; j2 <= j+k; j2++) {
								if(i2 >= 10 || j2 >= 10 || map[i2][j2] != 1){
									break loop;
								}
							}
						}
						count++;
					}
					msize[i][j] = count;
				}				
			}
		}
		
		dfs(0,0);
		if(answer == Integer.MAX_VALUE) answer = -1;
	}

	public static void dfs(int x, int y) {
		int i = 0;
		int j = 0;
		
		if(answer <= count) return;
		
		loop:for(i = x; i < 10; i++) {
			for(j = 0; j < 10; j++) {
				if(map[i][j] == 1 && !cover[i][j]) {
					x = i;
					y = j;
					break loop;
				}
			}
		}
		if( i == 10 ) {
			boolean check = true;
			for(i = x; i < 10; i++) {
				for(j = y; j < 10; j++) {
					if(map[i][j] == 1 && !cover[i][j]) {
						check = false;
					}
				}
			}
			if(check == true) {
				if(answer > count) answer = count;
			}
			return;
		}

		//if(x >= 10 || y >= 10) return;
		
		loop:for(i = msize[x][y]; i > 0; i--) {
			if(visit[x][y] == 0 && paper[i]+1 <= 5) {
				for(j = 0 ; j < i; j++) {
					for(int k = 0; k < i; k++) {
						if(cover[x+j][y+k] == true) {
							continue loop;
						}
					}
				}
				visit[x][y] = i;
				for(j = 0 ; j < i; j++) {
					for(int k = 0; k < i; k++) {
						cover[x+j][y+k] = true;
					}
				}
				paper[i]++;
				count++;
				if(y == 9) dfs(x+1, 0);
				else dfs(x, y+1);
				count--;
				paper[i]--;
				visit[x][y] = 0;
				for(j = 0 ; j < i; j++) {
					for(int k = 0; k < i; k++) {
						cover[x+j][y+k] = false;
					}
				}				
			}
		}	
	}
}
	

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

 

 

 

13977번: 이항 계수와 쿼리

\(M\)개의 자연수 \(N\)과 정수 \(K\)가 주어졌을 때 이항 계수 \(\binom{N}{K}\)를 1,000,000,007로 나눈 나머지를 구하는 프로그램을 작성하시오.

www.acmicpc.net

 

 


 

 

 

  • 생각

 

 

[JAVA] 백준 11401번 : 이항 계수 3

코드 정답 코드 : onsil-thegreenhouse.github.io/programming/problem/2018/04/02/problem_combination/를 참고해서 이해하였다. import java.io.BufferedReader; import java.io.InputStreamReader; import jav..

qazyj.tistory.com

문제와 비슷한 문제이다. 하지만 위와 비슷한 방법으론 시간 초과가 뜬다.

시간 초과가 뜨는 이유는 팩토리얼 구하는 부분때문인데 위의 문제에서는 한번만 작업을 수행하기때문에 문제가 없지만 해당 문제에서는 M번만큼의 팩토리얼 작업을 수행하기 때문이다.

 

이것을 줄이기 위해서 배열로 팩토리얼 작업을 수행했다.

 

 

 

 

 

 

  • 코드

정답 코드 : 미리 팩토리얼을 구한 뒤 역원까지 구해준 뒤 상수시간만에 해당 값을 도출

 

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


/* [페르마의 소정리] _ 혜민 코드 참고
a^(p-1) % p = 1
(a/b) % M = ((a % M) * (b^-1 % M)) = ((a % M) * (b^(M-2) % M))
*/

public class Main {
	private static  StringBuilder sb;
    private static int MOD;
    private static long[] F; // 8MB

	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);
		sb = new StringBuilder();
		F = new long[4000001]; // 8MB
		MOD = 1000000007;

        setFactorial();

        int T = in.nextInt();
        while (T-- > 0) {
            int N = in.nextInt();
            int K = in.nextInt();
            sb.append(Combination(N, K)).append('\n');
        }
	}

    private static long Combination(int N, int K) {
        long numer = F[N];
        long denom = (F[N - K] * F[K]) % MOD;
        denom = Pow(denom, MOD - 2);
        
        return (numer * denom) % MOD;
    }

    private static long Pow(long n, int k) {
        long base = 1;
        while (k > 0) {
            if (k % 2 == 1) { base *= n; base %= MOD; }
            n *= n; n %= MOD;
            k /= 2;
        }

        return base;
    }

    private static void setFactorial() {
        F[0] = 1; F[1] = 1;
        for (int i = 2; i < 4000001; i++) {
            F[i] = i * F[i - 1];
            F[i] %= MOD;
        }
    }
}
	

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

 


 

  • 생각

 맵에서 1은 섬을 나타내고 0은 바다를 나타낸다 섬은 상하좌우 대각선 총 8방향으로 이어져있을때, 주어진 배열의 섬의 수를 구하는 문제이다. bfs를 이용하여 8방향을 탐색하면 될 것 같다라고 생각했다.

 

 

  • 코드

정답 코드 : dfs를 통해 구현하였다. check되지 않고 1인 수를 발견하면 주변에 포함된 1의 좌표를 check해주며 result+1을 해준다.

 

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

public class Main {
    static final int[][] xy = {{0, 1}, {0, -1}, {1, 0}, {1, 1}, {1, -1}, {-1, 0}, {-1, 1}, {-1, -1}};
    static boolean[][] islands;
    static StringBuilder sb;

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

	// 데이터
	private static void SetData() throws Exception {
		InputReader in = new InputReader(System.in);
		sb = new StringBuilder();
		
        while(true) {
            int x = in.nextInt();
            int y = in.nextInt();

            if(x == 0 && y == 0) {
                return;
            }

            islands = new boolean[y + 2][x + 2];

            for(int i = 1; i <= y; i++) {
                for(int j = 1; j <= x; j++) {
                    islands[i][j] = in.nextInt() > 0;
                }
            }
            
            int result = 0;
            for(int i = 1; i <= y; i++) {
                for(int j = 1; j <= x; j++) {
                    if(islands[i][j]) {
                        result++;
                        dfs(i, j, islands);
                    }
                }
            }
            sb.append(result + "\n");
        }
	}

    private static void dfs(int x, int y, boolean[][] islands) {
        for(int[] XY : xy) {
            int r = x + XY[0];
            int c = y + XY[1];

            if(islands[r][c]) {
                islands[r][c] = false;
                dfs(r, c, islands);
            }
        }
    }
}
	

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