2866번: 문자열 잘라내기

첫 번째 줄에는 테이블의 행의 개수와 열의 개수인 R과 C가 주어진다. (2 ≤ R, C ≤ 1000) 이후 R줄에 걸쳐서 C개의 알파벳 소문자가 주어진다. 가장 처음에 주어지는 테이블에는 열을 읽어서 문자

www.acmicpc.net

 

 

 


 

 

  • 풀이

 

1. 이분탐색을 통해 열의 인덱스 (mid, end) 를 보내줍니다.

2. mid부터 end까지의 중복되는 문자열이 있는지 찾습니다.

3. 문자열이 있다면 right를 mid -1로 초기화 시키며 더 위의 열을 확인해줍니다.

4. 문자열이 없다면 left를 mid+1로 초기화 시키며 더 아래의 열을 확인해줍니다.

5. 2~4의 작업을 반복합니다.

 

위의 설명대로 구현하였으며, 같은 문자열이 있는지 check해줄 때의 데이터는 순서가 상관없으므로 더 빠른 HashSet을 이용했습니다.

 

 

 

  • 코드

 

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

public class Main {
	static int R, C, answer;
	static char[][] 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);

		R = in.nextInt();
		C = in.nextInt();
		array = new char[R][C];

		for (int i = 0; i < R; i++) {
			String s = in.nextLine();
			for (int j = 0; j < C; j++) {
				array[i][j] = s.charAt(j);
			}
		}

		binarySearch(1, R - 1, R - 1);
	}

	private static boolean check(int start, int end) {
		Set<String> s = new HashSet<>();

		for (int j = 0; j < C; j++) {
			String temp = "";
			for (int i = start; i <= end; i++)
				temp += array[i][j];

			if (!s.contains(temp))
				s.add(temp);
			else
				return false;
		}

		return true;
	}

	private static void binarySearch(int left, int right, int end) {
		while (left <= right) {

			int mid = (left + right) / 2;

			boolean flag = check(mid, end);

			if (flag) {
				if (answer < mid)
					answer = mid;
				left = mid + 1;
			} else {
				right = mid - 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;
	}
}

 

 

 

  • 더 빠르고 메모리 적게 잡아먹는 다른 사람 코드

아래의 코드는 arrayList에 이미 모든 열로 이어진 행의 개수를 다 넣은 뒤 subString으로 더 빠르게 확인해 준 방법이다.

 

방법은 같지만 반복해서 Set에 데이터를 추가해주는 저의 코드에 비해 반복없이 1번만 작업해줌으로서 훨씬 시간을 단축해준 코드입니다. 

 

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

public class Main {

	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		int R = Integer.parseInt(st.nextToken());
		int C = Integer.parseInt(st.nextToken());
		char[][] arr = new char[R][C];

		for (int i = 0; i < R; i++) {
			arr[i] = br.readLine().toCharArray();
		}

		ArrayList<String> list = new ArrayList<>();
		StringBuilder sb = new StringBuilder("");
		for (int i = 0; i < C; i++) {
			sb.setLength(0);
			for (int j = 0; j < R; j++) {
				sb.append(arr[j][i]);
			}
			list.add(sb.toString());
		}

		int count = 0, start = 0, end = R;
		ArrayList<String> tempList = new ArrayList<>();
		while (start <= end) {
			tempList.clear();
			int mid = (start + end) / 2;
			for (int i = 0; i < list.size(); i++) {
				String temp = list.get(i);
				temp = temp.substring(mid, temp.length());
				if (!tempList.contains(temp)) {
					tempList.add(temp);
				} else {
					break;
				}
			}
			if (tempList.size() != list.size()) {
				end = mid - 1;
			} else {
				start = mid + 1;
				count = mid;
			}
		}
		System.out.print(count);
	}
}

 

14725번: 개미굴

첫 번째 줄은 로봇 개미가 각 층을 따라 내려오면서 알게 된 먹이의 정보 개수 N개가 주어진다.  (1 ≤ N ≤ 1000) 두 번째 줄부터 N+1 번째 줄까지, 각 줄의 시작은 로봇 개미 한마리가 보내준 먹이

www.acmicpc.net

 

 

 

 


 

  • 풀이

 

개미굴의 각 층을 표현하고 같은 층의 경우 사전순으로 먼저 출력되야 합니다.

 

TreeMap의 장점 중 하나는 자동으로 key값에 의해 자동 정렬 된다는 것입니다. (우선순위 큐와 비슷한 느낌)

 

저 같은 경우 Node라는 class를 만들어 현재 string과 자식 Treemap을 생성해 주었다.

 

 

맨 처음 연결시킬 string 입력이 올 시 now라는 Node를 만들어 준 뒤 root의 위치를 할당합니다. 그 후 입력된 String이 자식 Treemap의 키값 중 해당 String으로 된 TreeMap이 없다면 새롭게 자식 TreeMap을 만들어 연결 시켜줍니다. 그 후, now를 자식 node를 가리키게 합니다. (해당 동작은 자식 노드를 게속 연결시켜주기 위함.)

 

연결이 모두 다 되었다면, root에 연결된 자식 TreeMap을 하나씩 꺼내서 자식을 타고가면서 출력해주면 됩니다.

저는 재귀 형식으로 구현했습니다.

 

 

 


 

  • 코드

 

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

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

        int n = in.nextInt();
        Trie trie = new Trie("");
        Trie node;
        sb = new StringBuilder();
        
        while(n-- > 0) {
        	String[] temp = in.nextLine().split(" ");
            int k = Integer.parseInt(temp[0]);
            node = trie;
            
            for(int j = 0 ; j < k ; j++) {
                String name = temp[j+1];
                
                if(!node.list.containsKey(name)) 
                    node.list.put(name, new Trie(name));
                
                node = node.list.get(name);
            }
        }
        
        print(trie, -1);
    }
    
    public static void print(Trie trie, int depth) {
        if(depth != -1) {
            for(int i = 0; i < depth; i++) {
                sb.append("--");
            }
            sb.append(trie.name).append("\n");
        }
        
        for(Trie tree : trie.list.values()) {
            print(tree, depth+1);
        }
    }
}

class Trie{
    TreeMap<String, Trie> list;
    String name;
    
    Trie(String name) {
        list = new TreeMap<>();
        this.name = name;
    }
}

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

오늘은 GitHub 원격 리포지토리에 코드를 푸시하려고 하는데 터미널에 다음 오류가 발생했습니다.

 

react-fileupload git: git push remote: Support for password authentication was removed on September 6, 2021. Please use a personal access token instead. remote: Please see https://github.blog/2020-12-15-token-authentication-requirements-for-git-operations/ for more information. fatal: unable to access 'https://github.com/qazyj/Algorithm.git/': The requested URL returned error: 403

 

이 오류는 보안상의 이유로 GitHub가 2021년 8월 13일부터 암호 기반 인증을 제거함을 알려줍니다.

 

  1. GitHub.com을 열고 프로필 사진을 클릭한 다음 설정을 클릭합니다.
  2. 이제 페이지 하단으로 스크롤하여 개발자 설정 탭을 클릭합니다.
  3. 이제 개인용 액세스 토큰을 클릭하고 이름과 만료일 등을 입력하여 새 토큰을 생성합니다.
  4. 개인 액세스 토큰을 성공적으로 생성했으면 복사합니다.

1. 이제 오류가 발생한 Git 저장소를 열고 다음 명령을 실행하여 현재 원본을 제거합니다.

git remote remove origin

 

 

2.터미널에서 다음 명령을 사용하여 새 원본을 추가합니다.

git remote add origin https://<발급받은 토큰>@github.com/<유저아이디>/<레포지토리 이름>.git

 

예를 들어:

git remote add origin https://gh-3jdj234rjfjdjjd2n2@github.com/qazyj/demo.git

이제 git push오류 없이 명령을 사용하여 GitHub에 코드를 푸시할 수 있습니다.

 


 

  • 코드

정답 코드 : 가장 긴 증가하는 부분 수열은 dp로 풀었었는데, dp로 풀게되면 문제가 N의 수가 높아질 경우 시간 복잡도가 O(N^2)이기 때문에 너무 오래걸린다. 해결책은 LIS 알고리즘이다. LIS 알고리즘은 시간 복잡도 O(NlogN)이다.

 

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

public class Main {
	static int N, answer;
	static int[] inputArray, LIS;
	
	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();
		inputArray = new int[N];
		LIS = new int[N];
		answer = 0;

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

		LIS[0] = inputArray[0];
		int j = 0;

		for (int i = 1; i < N; i++) {
			if (LIS[j] < inputArray[i]) {
				LIS[++j] = inputArray[i];
			} else {
				int temp = binarySearch(0, j, inputArray[i]);
				LIS[temp] = Math.min(LIS[temp], inputArray[i]);
			}
		}

		answer = j + 1;
	}

	static int binarySearch(int startIndex, int endIndex, int key) {
		while (startIndex <= endIndex) {
			int mid = (startIndex + endIndex) / 2;
			if (LIS[mid] < key) {
				startIndex = mid + 1;
			} else {
				endIndex = mid - 1;
			}
		}
		return startIndex;
	}
}

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

 

 

  • LIS 알고리즘

LIS 알고리즘은 주어진 수열 내에서 가장 긴 부분 수열을 찾아내는 알고리즘이다. 

 

최적화의 핵심은 Binary Search이다. 위의 dp처럼 O(N)의 방법으로 수열을 처음부터 확인할건데 이번에는 이분탐색을 이용하여 LIS를 유지하기 위한 최적의 위치에다가 수를 삽입하는 방식입니다.

 

 

2617번: 구슬 찾기

모양은 같으나, 무게가 모두 다른 N개의 구슬이 있다. N은 홀수이며, 구슬에는 번호가 1,2,...,N으로 붙어 있다. 이 구슬 중에서 무게가 전체의 중간인 (무게 순서로 (N+1)/2번째) 구슬을 찾기 위해서

www.acmicpc.net

 

 

 

 


 

 

 

  • 풀이

 

 

highDown 배열에 dfs방식을 통해 자신보다 높은 수, 적은 수의 개수를 저장해주었다.

자신보다 낮은수 or 높은수가 (N+1)/2 보다 높으면 중간 구슬이 될 수 없기때문에 answer을 +1해주었다.

 

 

 

  • 코드

 

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

public class Main {
	static int N, M, answer;
	static ArrayList<Integer>[] array;
	static int[][] highDown;
	static boolean[] check;

	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();
		answer = 0;
		array = new ArrayList[N+1];
		highDown = new int[N+1][2];
		
		for(int i = 1; i <= N; i++) {
			array[i] = new ArrayList<>();
		}
		
		for(int i = 1; i <= M; i++) {
			array[in.nextInt()].add(in.nextInt());
		}
		
		for(int i = 1; i <= N; i++) {
			check = new boolean[N+1];
			dfs(i, i);
		}
		
		for(int i = 1; i <= N; i++) {
			if(highDown[i][0] >= (N+1)/2 || highDown[i][1] >= (N+1)/2)
				answer++;
		}
	}
	
	private static void dfs(int index, int current) {
		check[current] = true;
		for(int i = 0 ; i < array[current].size(); i++) {
			int next = array[current].get(i);
			if(check[next]) continue;
			
			highDown[index][0]++;
			highDown[next][1]++;
			dfs(index, next);
		}
	}
}

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

 

10800번: 컬러볼

첫 줄에는 공의 개수를 나타내는 자연수 N이 주어진다(1 ≤ N ≤ 200,000). 다음 N개의 줄 중 i번째 줄에는 i번째 공의 색을 나타내는 자연수 Ci와 그 크기를 나타내는 자연수 Si가 주어진다(1 ≤ Ci ≤ N

www.acmicpc.net

 

 

 

 


 

 

 

  • 풀이

 

size 순으로 오름차순 정렬 후 size 누적합을 구하고 같은 컬러의 색상을 빼기 위해 배열을 만들어 같은 컬러의 색상도 따로 누적합을 구하면서 sum - index[color 인덱스] 식으로 구해주었다.

 

 

  • 코드

 

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

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

		N = in.nextInt();
		array = new int[N + 1];
		index = new int[N + 1];

		sb = new StringBuilder();

		ArrayList<Ball> arrayList = new ArrayList<>();
		for (int i = 0; i < N; i++) {
			arrayList.add(new Ball(i+1, in.nextInt(), in.nextInt()));
		}
		Collections.sort(arrayList);
		
		int sum = 0;
		int temp = 0;
        for (int i = 0; i < N; i++) {
            Ball ball = arrayList.get(i);
            
            for(int j = temp; arrayList.get(j).size < ball.size; j++) {
            	Ball ballTemp = arrayList.get(j);
            	         	
                sum += ballTemp.size;
                index[ballTemp.color] += ballTemp.size;
                temp++;
            }

            array[ball.index] = sum - index[ball.color];
        }

		for (int i = 1; i <= N; i++) {
			sb.append(array[i]).append("\n");
		}
	}
}

class Ball implements Comparable<Ball> {
	int index;
	int color;
	int size;

	public Ball(int index, int color, int size) {
		this.index = index;
		this.color = color;
		this.size = size;
	}

	@Override
	public int compareTo(Ball ball) {
		 return this.size - ball.size;
	}
}

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

 

10653번: 마라톤 2

젖소 박승원이 2번째 와 4번째 체크포인트를 건너뛸경우 경로는 (0,0) -> (1,1) -> (2,2) 로 4가 된다. 이보다 더 짧게 달릴수는 없다.

www.acmicpc.net

 

 

 

 

 


 

 

 

  • 코드

 

 

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

public class Main {
	static int N, K, answer;
	static int[][] vertex, dp, distance;	
	
	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();
		K = in.nextInt();
		vertex = new int[N + 1][2];
		dp = new int[N + 1][K + 1];
		distance = new int[N + 1][N + 1];
		
		for (int i = 1; i <= N; i++) {
			vertex[i][0] = in.nextInt();
			vertex[i][1] = in.nextInt();
			Arrays.fill(dp[i], -1);
		}

		for (int i = 1; i < N; i++) {
			for (int j = i + 1; j <= N; j++) {
				distance[i][j] = Calculate(vertex[i][0], vertex[i][1], vertex[j][0], vertex[j][1]);
			}
		}
		
		answer = DP(N, K);
	}	

	private static int DP(int n, int k) {
		if (dp[n][k] != -1)
			return dp[n][k];
		
		if (n == 1)
			return 0;
		
		int ans = Integer.MAX_VALUE;
		for (int i = 0; i <= k; i++) {
			if (1 <= n - 1 - i)
				ans = Math.min(ans, DP(n - i - 1, k - i) + distance[n - i - 1][n]);
		}
		
		return dp[n][k] = ans;
	}
	
	static int Calculate(int x1, int y1, int x2, int y2) {
		return Math.abs(x1 - x2) + Math.abs(y1 - y2);
	}
}

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

 

2234번: 성곽

첫째 줄에 두 정수 n, m이 주어진다. 다음 m개의 줄에는 n개의 정수로 벽에 대한 정보가 주어진다. 벽에 대한 정보는 한 정수로 주어지는데, 서쪽에 벽이 있을 때는 1을, 북쪽에 벽이 있을 때는 2를,

www.acmicpc.net

 

 

 

 


 

 

 

  • 풀이

 

비트마스킹 + bfs

 

 

  • 코드

 

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

public class Main {
	static int n, m, numberOfRoom, BiggestRoom, removeWallBiggestRoom;
	static int[][] array;
	static int[][] group;
	static boolean[][] check;
	static int[] x = { 0, -1, 0, 1 };
	static int[] y = { -1, 0, 1, 0 };
	static int[] dir = { 1, 2, 4, 8 };
	static HashMap<Integer, Integer> map;

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

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

		m = in.nextInt();
		n = in.nextInt();
		array = new int[n][m];
		check = new boolean[n][m];
		group = new int[n][m];
		numberOfRoom = 0;
		BiggestRoom = 0;
		removeWallBiggestRoom = 0;
		map = new HashMap<>();

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

		int groupCount = 1;
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				if (check[i][j])
					continue;

				int count = bfs(i, j, groupCount);
				numberOfRoom++;
				map.put(groupCount++, count);
				BiggestRoom = Math.max(BiggestRoom, count);
			}
		}

		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				removeWall(i, j);
			}
		}
	}

	private static int bfs(int i, int j, int groupCount) {
		Queue<int[]> queue = new LinkedList<>();
		queue.add(new int[] { i, j });
		check[i][j] = true;
		group[i][j] = groupCount;
		int count = 1;
		while (!queue.isEmpty()) {

			int[] location = queue.poll();
			for (int direction = 0; direction < 4; direction++) {
				if ((array[location[0]][location[1]] & (1 << direction)) != 0)				continue;

				int r = location[0] + x[direction];
				int c = location[1] + y[direction];
				
				if (r < 0 || r >= n || c < 0 || c >= m || check[r][c])				continue;

				count++;
				check[r][c] = true;
				group[r][c] = groupCount;
				queue.add(new int[] { r, c });
			}
		}
		return count;
	}

	private static void removeWall(int i, int j) {
		int sum = map.get(group[i][j]);

		for (int direction = 0; direction < 4; direction++) {

			int r = i + x[direction];
			int c = j + y[direction];

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

			if ((array[i][j] & (1 << direction)) == 0 || group[i][j] == group[r][c])			continue;
			
			sum += map.get(group[r][c]);
			removeWallBiggestRoom = Math.max(removeWallBiggestRoom, sum);
			sum -= map.get(group[r][c]);
		}
	}
}

class Cow {
	int x;
	int y;

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

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