728x90
 

14501번: 퇴사

첫째 줄에 백준이가 얻을 수 있는 최대 이익을 출력한다.

www.acmicpc.net

입력이 N (1 ≤ N ≤ 15)라길래 브루트포스로 풀었다.

조합은 시간 복잡도가 계승(팩토리얼)함수이기  때문에 n이 20 정도만 돼도 답을 구하기가 힘들다.

따라서 입력이 1 ≤ N ≤ 15 이라는 것을 보고 힌트를 얻었다. 마음놓고 조합으로 풀어도 된다는 것이구나.

 

조합(Combination)으로 N개 중 1개를 고르는 경우부터 N개를 고르는 경우까지 모든 경우를 다 구하고

그러고 나서 나중에 조건을 체크했다.

#include <iostream>
#include <vector>
#include <tuple>
using namespace std;

int** arr;
int n;
vector<int> profit;

void select(vector<bool> visited, vector<tuple<int, int, int>> result, int theNumberOfSelect, int num) {

	if (num == theNumberOfSelect) {

		int total = 0;
		if (get<2>(result[0]) + get<0>(result[0]) > n) {
			return;
		}
		for (int i = 1; i < theNumberOfSelect; i++) {
			if (get<2>(result[i]) + get<0>(result[i]) > n) {
				return;
			}
			if (get<2>(result[i - 1]) + get<0>(result[i - 1]) > get<2>(result[i])) {
				return;
			}
		}
		for (int i = 0; i < theNumberOfSelect; i++) {
			total += get<1>(result[i]);
		}

		profit.push_back(total);
		return;
	}
	for (int i = 0; i < n; i++) {
		if (num != 0) {
			if (get<2>(result[num - 1]) < i) {
				if (!visited[i]) {
					visited[i] = true;
					result[num] = make_tuple(arr[i][0], arr[i][1], i); //걸리는 기간, 받는 금액, 시작 날짜
					select(visited, result, theNumberOfSelect, num + 1);
					visited[i] = false;
				}
			}
		}
		else {
			if (!visited[i]) {
				visited[i] = true;
				result[num] = make_tuple(arr[i][0], arr[i][1], i); //걸리는 기간, 받는 금액, 시작 날짜
				select(visited, result, theNumberOfSelect, num + 1);
				visited[i] = false;
			}
		}
	}
}

int main() {
	cin >> n;
	arr = new int*[n];
	for (int i = 0; i < n; i++) {
		arr[i] = new int[2];
	}
	for (int i = 0; i < n; i++) {
		cin >> arr[i][0] >> arr[i][1];
	}
	for (int i = 0; i < n; i++) {
		vector<tuple<int, int, int>> result(i + 1);
		vector<bool> visited(n);
		for (int j = 0; j < n; j++) {
			visited[i] = false;
		}
		select(visited, result, i + 1, 0);
	}
	int maxProfit = 0;
	for (int i = 0; i < profit.size(); i++) {
		if (profit[i] > maxProfit) maxProfit = profit[i];
	}
	cout << maxProfit;
	return 0;
}

 

728x90
728x90
 

1110번: 더하기 사이클

0보다 크거나 같고, 99보다 작거나 같은 정수가 주어질 때 다음과 같은 연산을 할 수 있다. 먼저 주어진 수가 10보다 작다면 앞에 0을 붙여 두 자리 수로 만들고, 각 자리의 숫자를 더한다. 그 다음, 주어진 수의 가장 오른쪽 자리 수와 앞에서 구한 합의 가장 오른쪽 자리 수를 이어 붙이면 새로운 수를 만들 수 있다. 다음 예를 보자. 26부터 시작한다. 2+6 = 8이다. 새로운 수는 68이다. 6+8 = 14이다. 새로운 수는 84이다. 8+4 =

www.acmicpc.net

#include <iostream>
using namespace std;

int main() {
	int n;
	cin >> n;
	int originalNumber = n;
	int count = 0;
	do {
		int a = n % 10;
		int b = (n / 10 + n % 10) % 10;
		n = a * 10 + b;
		count++;
	} while (n != originalNumber);
	cout << count;
	return 0;
}
728x90
728x90

단계별로 풀어보기 동적 계획법 1의 11단계 문제

LIS(Longest Increasing Subsequence) 문제이다.

 

11053번: 가장 긴 증가하는 부분 수열

수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오. 예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {10, 20, 10, 30, 20, 50} 이고, 길이는 4이다.

www.acmicpc.net

#include <iostream>
using namespace std;

int main() {
	int n;
	cin >> n;
	int* numbers = new int[n];
	int* dp = new int[n]; //i까지의 최장 증가하는 수열의 길이를 저장하는 배열
	for (int i = 0; i < n; i++) {
		cin >> numbers[i];
	}
	dp[0] = 0;
	for (int i = 0; i < n; i++) {
		int maxBeforeI = 0; //i 전까지 최장 증가하는 수열의 길이를 저장할 변수
		for (int j = 0; j < i; j++) { //i 전까지
			if (numbers[i] > numbers[j]) { //'증가하는' 조건을 만족하면서
				if (dp[j] > maxBeforeI) //더 긴 수열이 발견되면
					maxBeforeI = dp[j]; //업데이트
			}
		}
		dp[i] = maxBeforeI + 1; // i 전까지를 구했으니까 나 자신 i를 더해줘야 한다.
	}
	int maxDp = 0;
	for (int i = 0; i < n; i++) {
		if (dp[i] > maxDp)
			maxDp = dp[i];
	}
	cout << maxDp << endl;
	return 0;
}

동적 계획법의 특징 답게 특별한 계산 없이 해를 구할 수 있다.

나보다 작으면서 나보다 이전에 있는 LIS에 1만 더해주면 된다.

728x90

'알고리즘 문제' 카테고리의 다른 글

[백준] 14501번 퇴사  (0) 2020.01.29
[백준] 1110번 더하기 사이클  (0) 2020.01.29
[백준] 6603번 로또  (0) 2020.01.29
[백준] 1181번 단어 정렬  (0) 2020.01.29
[백준] 11050번 이항계수 1  (0) 2020.01.28
728x90

우선 입출력 스트림의 특징부터 알아보자.

1. 입출력 스트림은 선입선출 구조이다. 따라서 순차적(단방향)으로만 접근이 가능하다.

사실 양방향으로 다 되는 게 있긴 하다. (임의 접근 파일 스트림)

그래도 스트림은 기본적으로 순차적이다.

2. 입출력 스트림은 객체로 구성되어 있다. (자바에서는 기초형을 제외하고는 전부 다 객체이다.)

3.출력스트림과 입력스트림은 서로 연결해서 파이프라인 방식으로 만들 수 있다.

4. 지연 가능성이 있다. 출력을 하는데 CPU 속도와 프린터의 속도가 다를 수도 있으니까.

 

입출력 스트림은 다음과 같은 구조를 가지고 있다.

입출력 스트림은 크게 바이트 스트림과 문자 스트림으로 나눌 수 있다.

바이트 스트림은 일반적인 이진 데이터 파일을 처리할 때 사용한다. 이진스트림이라고도 한다.

문자 스트림은 한글, 영어 등 언어로 되어 있는 파일을 처리할 때 유용하다. 동영상, 이미지 등을 처리할 때에는 적합하지 않다.

 

InputStream, OutputStream, Reader, Writer 4개의 클래스는 모두 추상클래스이다.

왜 추상클래스일까?

입력 스트림의 경우 입력이 키보드에서 될 수도 있고 마우스에서 입력될 수도 있고

출력 스트림의 경우 모니터에 출력할 수도 있고 프린터에 출력할 수도 있고 네트워크를 통해서 다른 곳으로 출력할 수도 있고 다 다르다.

그렇기 때문에 입출력 메소드인 read(), write() 메소드를 구현할 수가 없다.

따라서 4개의 추상클래스를 만들어 놓고 사용할 때에는 구현된 자식 클래스를 이용한다.

 

입출력 스트림의 사용 과정은 다음과 같다.

1. 스트림을 열고

2. 스트림으로 처리하고

3. 스트림을 닫는다.

마지막에는 close() 메소드로 반드시 스트림을 닫아줘야 한다.

스트림을 여는 open()이라는 메소드는 없다. 스트림 객체를 생성하는 것 자체가 스트림을 여는 것이다.

 

먼저 바이트 스트림부터 살펴보자.

 

살펴보기 전에 각 클래스의 특징부터 설명하자면

바이트 스트림은 이미지나 동영상을 처리할 때 적합하다. 바이트 스트림은 모두 InputStream, OutputStream의 자식클래스들이다.

InputStream에서는 FileInputStream, DataInputStream, BufferedInputStream을 자주 사용한다.

파일을 다룰 때에는 FileInputStream을, 데이터 자체를 다루고 싶을 때에는 DataInputStream을 사용하면 된다.

데이터 자체를 다룬다는 말은 메모리에 저장되어 있는 그 데이터를 그대로 다루겠다는 것이다.  

만약에 int 타입의 1이라는 데이터가 있다면 00000000000000000000000000000001로 다루는 것을 말한다.

BufferedStream은 말 그대로 버퍼를 이용하는 것이다. 속도가 차이나기 때문에 버퍼에 잠시 보관하는 것이다.

이 중에서도 우리는 주로 FileInputStream과 BufferedInputStream을 자주 사용한다.

 

OutputStream에서는 FileOutputStream, BufferedOutputStream, PrintStream을 자주 쓰는데 PrintStream은 다른 것들과 특징이 조금 달라서 기억해 둘 필요가 있다. 그 특징은 뒤에서 배울 것이다.

 

이제 정말 바이트 스트림을 알아보자

 

InputStream과 OutputStream은 모든 자식 바이트 스트림에서 공통으로 사용하는 메소드(read(), write() 등)를 포함하는 바이트 스트림의 최상위 클래스이다.

InputStream 클래스에는 read(), OutputStream 클래스에는 write()라는 추상메소드가 있다. 앞에서 말했지만 이 두 메소드는 구현을 할 수가 없다.

 

 

InputStream (Java SE 10 & JDK 10 )

Reads all bytes from this input stream and writes the bytes to the given output stream in the order that they are read. On return, this input stream will be at end of stream. This method does not close either stream. This method may block indefinitely read

docs.oracle.com

오라클 홈페이지에서 Java API를 보면 InputStream은 추상클래스이고 Closeable의 구현 클래스인 것을 알 수 있다.

Closeable이라는 것은 자원을 close해야 한다는 것이다. Closeable의 자식클래스로는 AutoCloseable이 있다.

 

 

 

 

OutputStream (Java SE 10 & JDK 10 )

Flushes this output stream and forces any buffered output bytes to be written out. The general contract of flush is that calling it is an indication that, if any bytes previously written have been buffered by the implementation of the output stream, such b

docs.oracle.com

OutputStream도 마찬가지로 추상클래스이고 Closeable의 구현 클래스인 것을 볼 수 있다. 한 가지 다른 것은 Flushable의 구현 클래스라는 것이다. 뒤에서 배우겠지만 출력 스트림은 flush를 해줘야 한다.

 

InputStream의 주요 메소드

int available() 읽을 수 있는 바이트의 개수 반환.
void close() 입력 스트림을 닫는다.
abstract int read() 한 바이트를 읽고 그 읽은 것을 int로 리턴한다.
int read(byte[] b) 1바이트씩 읽어 배열에 집어넣고 몇 바이트 읽었는지 반환

데이터 읽을 게 있는지 없는지 체크하려면 available() 메소드를 사용한다. 헷갈릴 수도 있는데 이 메소드는 boolean 타입이 아니다. 기억해 두자.

InputStream객체.available() 해보고 0보다 클 경우에만 읽으면 된다.

read() 메소드가 특이한 것은 1byte를 읽어서 int 타입으로 반환한다는 것이다. int는 4바이트이다. 즉, 앞쪽 3바이트는 사용을 안 한다는 것이다. read() 메소드는 1바이트를 읽어서 읽은 내용을 반환하는데 int 타입으로 반환한다는 것 잊지 말자.

read() 메소드는 만약 더 이상 읽을 것이 없으면 -1을 반환한다. -1을 반환하기 위해서 read() 메소드의 반환 타입이 int 타입인 것이다.

 

OutputStream의 주요 메소드

void close() 출력 스트림을 닫는다.
void flush() 버퍼를 비운다.
abstract void write(int b) b를 바이트로 변환해서 1바이트를 쓴다.
void write(byte[] b) 바이트 배열 b를 쓴다.

flush()라는 것은 InputStream에는 없고 출력 스트림에만 있는 메소드이다. flush는 뭘까?

대부분의 운영체제나 JVM은 read(입력), write(출력)를 효율적으로 하기 위해서 버퍼를 사용한다.

컴퓨터가 처리하는 속도와 출력장치가 출력하는 속도를 비교하면 출력장치가 출력하는 속도가 훨씬 느리다.

예를 들어 출력 장치가 모니터라고 하자.

컴퓨터의 처리와 모니터가 출력하는 것은 속도 차이가 나기 때문에 출력을 효율적으로 하기 위해서 일단 버퍼에 써서 모아놨다가 나중에 한꺼번에 출력(write)을 한다.

System.in, System.out, System.err은 각각 표준 입력, 표준 출력, 표준 오류 장치이다. 표준 장치들은 시스템에서 바로 쓰기 때문에 효율적으로 사용하는 것이 좋으므로 버퍼를 사용한다. 따라서 내가 System.out.write(b) 하면 모니터에 바로 b가 나타나는 것이 아니라 버퍼에 모아둔다.

그 이후에 계속 써도 일단 버퍼에 쓴다. 그러고 나서 버퍼가 꽉 차면 그제서야 모니터에 출력한다.

그런데 나는 아직 버퍼가 꽉 차지는 않았지만 지금 바로 실제로 모니터에 출력을 하고 싶다면 그 때 사용하는 것이 flush 메소드이다. 그러면 버퍼에 있는 내용을 비우고 모니터에 바로 출력한다.

그런데 close() 메소드에는 flush()의 기능이 있어서 close()를 하면 자동으로 flush()가 된다. 더 이상 이 스트림 객체를 안 쓴다는 것이므로 끝내기 전에 버퍼에 있던 내용들은 출력하고 끝내야 하기 때문이다.

write() 메소드는 read() 메소드와 마찬가지로 1byte를 쓰지만 매개변수는 int 타입이다. 인자로 int 타입을 받아서 byte 타입으로 변환해서 1바이트를 쓴다.

 

import java.io.IOException;

public class IOStreamDemo {
    public static void main(String[] args) throws IOException {
        int b, len = 0;
        int ba[] = new int[100];
        System.out.println("---입력 스트림---");
        while ((b = System.in.read()) != '\n') {
            System.out.printf("%c(%d)", (char)b, b);
            ba[len++] = b;
        }
        System.out.println("\n\n---출력 스트림---");
        for(int i = 0; i < len; i++)
            System.out.write(ba[i]);
        System.out.flush();
    }
}

public static void main(String[] args) 뒤에 throws IOException이라고 예외 처리를 한 것을 볼 수 있는데

입출력 장치를 이용할 때에는 거의 IOException이 일어나기 때문에 반드시 예외 처리를 해 줘야 한다.

예외처리를 해주지 않으면 다음과 같이 컴파일 에러가 난다. 따라서 예외 처리는 선택이 아니라 필수이다.

예외처리를 해주지 않으면 컴파일 에러가 남

이 글은 예외처리 글이 아니라서 예외처리를 자세히 설명하면 너무 산으로 갈 것 같아서 예외처리는 따로 설명을 하겠다.

아무튼 입출력을 할 때에는 무조건 IOException에 대한 예외 처리를 해줘야 한다는 것이다.

 

이 코드에서는 InputStream, OutputStream 객체를 따로 만들지는 않았고 표준 입력 장치인 System.in과 표준 출력 장치인 System.out을 사용했다. 키보드로부터 입력을 받고 모니터에 출력을 하겠다는 것이다.

while문을 돌면서 키보드로부터 1바이트를 읽어서 ba 배열에 저장한다.

여기에서 주목해야 할 것은 1바이트를 읽어서 b에 저장하는데 b는 int 타입이라는 것이다.

잊지 말자 read() 메소드는 1바이트를 읽어서 int를 리턴한다.

그렇게 읽은 것은 ba 배열에 저장하고 나중에 write 메소드로 모니터에 출력한다.

마지막에 System.out.flush()를 해준다. flush()를 해주지 않으면 모니터에 출력이 안 될 수도 있다.

 

실행 결과는 다음과 같다.

위 코드의 실행 결과

728x90
728x90
 

6603번: 로또

문제 독일 로또는 {1, 2, ..., 49}에서 수 6개를 고른다. 로또 번호를 선택하는데 사용되는 가장 유명한 전략은 49가지 수 중 k(k>6)개의 수를 골라 집합 S를 만든 다음 그 수만 가지고 번호를 선택하는 것이다. 예를 들어, k=8, S={1,2,3,5,8,13,21,34}인 경우 이 집합 S에서 수를 고를 수 있는 경우의 수는 총 28가지이다. ([1,2,3,5,8,13], [1,2,3,5,8,21], [1,2,3,5,8,34], [1,2

www.acmicpc.net

#include <iostream>
using namespace std;

void select(int numbers[], int result[], bool visited[], int n, int num) {
	if (num == 6) {
		for (int i = 0; i < 6; i++) {
			cout << result[i] << " ";
		}
		cout << endl;
		return;
	}
	for (int i = 0; i < n; i++) {
		if (num != 0) {
			if (!visited[i] && numbers[i] > result[num - 1]) {
				visited[i] = true;
				result[num] = numbers[i];
				select(numbers, result, visited, n, num + 1);
				visited[i] = false;
			}
		}
		else {
			if (!visited[i]) {
				visited[i] = true;
				result[num] = numbers[i];
				select(numbers, result, visited, n, num + 1);
				visited[i] = false;
			}
		}
	}
}

int main() {
	while (true) {
		int n;
		cin >> n;
		if (n == 0) break;
		int* numbers = new int[n];
		for (int i = 0; i < n; i++) {
			cin >> numbers[i];
		}
		int* result = new int[n];
		bool* visited = new bool[n];
		for (int i = 0; i < n; i++) {
			visited[i] = false;
		}
		select(numbers, result, visited, n, 0);
		cout << endl;
	}
	return 0;
}
728x90
728x90
 

1181번: 단어 정렬

첫째 줄에 단어의 개수 N이 주어진다. (1≤N≤20,000) 둘째 줄부터 N개의 줄에 걸쳐 알파벳 소문자로 이루어진 단어가 한 줄에 하나씩 주어진다. 주어지는 문자열의 길이는 50을 넘지 않는다.

www.acmicpc.net

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        ArrayList<String> list = new ArrayList<>();
        Set<String> set = new HashSet<>();
        for(int i = 0; i < n; i++) {
            set.add(in.next());
        }
        Iterator<String> iterator = set.iterator();
        while(iterator.hasNext()) {
            list.add(iterator.next());
        }
        list.sort(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                if(o1.length() != o2.length())
                    return o1.length() - o2.length();
                else
                    return o1.compareTo(o2);
            }
        });
        for(int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
    }
}

HashSet을 List로 바꿀 수 있는 방법을 다시 공부해야겠다. 컬렉션 배웠던거 다시 복습해야지

728x90
728x90
 

11050번: 이항 계수 1

첫째 줄에 \(N\)과 \(K\)가 주어진다. (1 ≤ \(N\) ≤ 10, 0 ≤ \(K\) ≤ \(N\))

www.acmicpc.net

#include <iostream>
using namespace std;


int main() {
	int n, k;
	cin >> n >> k;
	int numerator = 1; //분자
	int denominator = 1; //분모
	for (int i = n; i > n - k; i--) {
		numerator *= i;
	}
	for (int i = k; i >= 1; i--) {
		denominator *= i;
	}
	cout << numerator / denominator;
	return 0;
}
728x90

'알고리즘 문제' 카테고리의 다른 글

[백준] 6603번 로또  (0) 2020.01.29
[백준] 1181번 단어 정렬  (0) 2020.01.29
[백준] 1065번 한수  (0) 2020.01.28
[백준] 17144번 미세먼지 안녕!  (0) 2020.01.28
[백준] 14891번 톱니바퀴  (0) 2020.01.27
728x90

단계별로 풀어보기 함수의 3단계 문제이다.

 

1065번: 한수

어떤 양의 정수 X의 자리수가 등차수열을 이룬다면, 그 수를 한수라고 한다. 등차수열은 연속된 두 개의 수의 차이가 일정한 수열을 말한다. N이 주어졌을 때, 1보다 크거나 같고, N보다 작거나 같은 한수의 개수를 출력하는 프로그램을 작성하시오. 

www.acmicpc.net

#include <iostream>
#include <tuple>
using namespace std;


int main() {
	int n;
	cin >> n;
	int count = 0;
	for (int i = 1; i <= n; i++) {
		if (i < 100) {
			count++;
		}
		else if (i < 1000){
			int a, b, c;
			a = i / 100;
			b = i / 10 % 10;
			c = i % 10;
			if (a - b == b - c) count++;
		}
	}
	cout << count << endl;
	return 0;
}
728x90

'알고리즘 문제' 카테고리의 다른 글

[백준] 1181번 단어 정렬  (0) 2020.01.29
[백준] 11050번 이항계수 1  (0) 2020.01.28
[백준] 17144번 미세먼지 안녕!  (0) 2020.01.28
[백준] 14891번 톱니바퀴  (0) 2020.01.27
[백준] 10809번 알파벳 찾기  (0) 2020.01.26
728x90
InputMethodManager imm;
imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);

이 3줄이면 소프트 키보드를 숨길 수 있다.

 

나는 주로 InputMethodManager 변수를

InputMethodManager imm;

이렇게 전역변수(클래스의 멤버변수)로 선언해놓고

 

onCreate() 메소드 안에서

imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); 

이렇게 초기화 해주고

 

필요한 부분에

imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);

이 코드를 넣어준다.

 

필요한 부분이란 대부분 onClick()메소드 안이다.

EditText에 뭔가를 입력하고 입력을 완료했을 때 누르는 그 버튼의 OnClickListener에 넣어주는 것이 일반적이다.

입력을 다 끝냈으니 이제 키보드가 필요없기 때문이다.

 

그런데 오늘은 onClick()메소드가 아닌 곳에서 키보드를 숨길 필요가 있었다.

 

EditText에 뭔가를 입력하다가 네비게이션 드로어(Navigation Drawer)를 열어야 하는 일이 있을 수도 있다.

그 때 키보드가 사라지지 않는다면

이렇게 드로어가 가려져서 사용하기에도 불편하고 보기에도 좋지 않은 상황이 발생한다.

 

네비게이션 드로어가 있는 액티비티를 만들었다면 MainActivity.java 파일에 이 코드가 있을 것이다.

ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);

drawer.addDrawerListener(toggle); 이라고 한 것을 보니 toggle은 리스너 객체인데 아무리 봐도 이벤트 핸들러 메소드를 추가할 수 있는 곳이 없어 보인다.

 

그냥 이렇게 해주면 된다.

ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close){
            @Override
            public void onDrawerOpened(View drawerView) {
                imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
            }
        };
drawer.addDrawerListener(toggle);

괄호 뒤에 중괄호를 열어주면 된다. 그러고 나서 alt+insert로 필요한 메소드를 오버라이딩하면 된다.

나는 드로어가 열렸을 때 키보드를 숨기고 싶어서 onDrawerOpened() 메소드 안에

imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);

이 코드 한 줄만 추가해줬다.

그랬더니 드로어를 열면 키보드가 자동으로 숨겨져서 훨씬 보기 좋아졌다.

 

반대로 키보드를 보이게 하고 싶으면

imm.showSoftInput(editText, 0);

이 코드 한 줄을 추가해주면 된다.

728x90
728x90

삼성 SW 역량 테스트 기출 문제인 17144번 문제

 

17144번: 미세먼지 안녕!

미세먼지를 제거하기 위해 구사과는 공기청정기를 설치하려고 한다. 공기청정기의 성능을 테스트하기 위해 구사과는 집을 크기가 R×C인 격자판으로 나타냈고, 1×1 크기의 칸으로 나눴다. 구사과는 뛰어난 코딩 실력을 이용해 각 칸 (r, c)에 있는 미세먼지의 양을 실시간으로 모니터링하는 시스템을 개발했다. (r, c)는 r행 c열을 의미한다. 공기청정기는 항상 왼쪽 열에 설치되어 있고, 크기는 두 행을 차지한다. 공기청정기가 설치되어 있지 않은 칸에는 미세먼

www.acmicpc.net

#include <iostream>
#include <tuple>
using namespace std;


int main() {
	int r, c, t;
	cin >> r >> c >> t;
	int** room = new int*[r];
	int** copyRoom = new int*[r];
	int** spreadRoom = new int*[r];
	for (int i = 0; i < r; i++) {
		room[i] = new int[c];
		copyRoom[i] = new int[c];
		spreadRoom[i] = new int[c];
	}
	pair<int, int> purifier[2];
	int index = 0;
	for (int i = 0; i < r; i++) {
		for (int j = 0; j < c; j++) {
			cin >> room[i][j];
			if (room[i][j] == -1) {
				purifier[index] = make_pair(i, j);
				index++;
			}
		}
	}
	for (int time = 0; time < t; time++) {
		if (time != 0) {
			for (int i = 0; i < r; i++) {
				for (int j = 0; j < c; j++) {
					room[i][j] = spreadRoom[i][j];
				}
			}
		}
		for (int i = 0; i < r; i++) {
			for (int j = 0; j < c; j++) {
				copyRoom[i][j] = room[i][j] / 5;
			}
		}
		for (int i = 0; i < r; i++) {
			for (int j = 0; j < c; j++) {
				spreadRoom[i][j] = 0;
			}
		}
		for (int i = 0; i < r; i++) {
			for (int j = 0; j < c; j++) {
				int count = 0;
				if (i - 1 >= 0 && !(i - 1 == purifier[0].first && j == purifier[0].second) && !(i - 1 == purifier[1].first && j == purifier[1].second)) {
					spreadRoom[i - 1][j] += copyRoom[i][j];
					count++;
				}
				if (i + 1 < r && !(i + 1 == purifier[0].first && j == purifier[0].second) && !(i + 1 == purifier[1].first && j == purifier[1].second)) {
					spreadRoom[i + 1][j] += copyRoom[i][j];
					count++;
				}
				if (j - 1 >= 0 && !(i == purifier[0].first && j - 1 == purifier[0].second) && !(i == purifier[1].first && j - 1 == purifier[1].second)) {
					spreadRoom[i][j - 1] += copyRoom[i][j];
					count++;
				}
				if (j + 1 < c && !(i == purifier[0].first && j + 1 == purifier[0].second) && !(i == purifier[1].first && j + 1 == purifier[1].second)) {
					spreadRoom[i][j + 1] += copyRoom[i][j];
					count++;
				}
				spreadRoom[i][j] += room[i][j] - count * copyRoom[i][j];
			}
		}


		int direction = 0; //위는 0, 오른쪽은 1, 아래는 2, 왼쪽은 3
		int row = purifier[0].first - 1;
		int col = purifier[0].second;
		while (true) {
			if (direction == 0) { //위쪽 방향일 때
				if (row - 1 >= 0) {
					spreadRoom[row][col] = spreadRoom[row - 1][col];
					row--;
				}
				else
					direction = 1;
			}
			if (direction == 1) { //오른쪽 방향일 때
				if (col + 1 < c) {
					spreadRoom[row][col] = spreadRoom[row][col + 1];
					col++;
				}
				else
					direction = 2;
			}
			if (direction == 2) { //아래 방향일 때
				if (row + 1 <= purifier[0].first) {
					spreadRoom[row][col] = spreadRoom[row + 1][col];
					row++;
				}
				else direction = 3;
			}
			if (direction == 3) {
				if (col - 1 >= 0) {
					if (spreadRoom[row][col - 1] == -1) {
						spreadRoom[row][col] = 0;
						col--;
						direction = 0;
						break;
					}
					else spreadRoom[row][col] = spreadRoom[row][col - 1];
					col--;
				}
			}
		}


		direction = 0;
		row = purifier[1].first + 1;
		col = purifier[1].second;
		while (true) {
			if (direction == 0) { //아래쪽 방향일 때
				if (row + 1 < r) {
					spreadRoom[row][col] = spreadRoom[row + 1][col];
					row++;
				}
				else
					direction = 1;
			}
			if (direction == 1) { //오른쪽 방향일 때
				if (col + 1 < c) {
					spreadRoom[row][col] = spreadRoom[row][col + 1];
					col++;
				}
				else
					direction = 2;
			}
			if (direction == 2) { //위쪽 방향일 때
				if (row - 1 >= purifier[1].first) {
					spreadRoom[row][col] = spreadRoom[row - 1][col];
					row--;
				}
				else direction = 3;
			}
			if (direction == 3) { //왼쪽 방향일 때
				if (col - 1 >= 0) {
					if (spreadRoom[row][col - 1] == -1) {
						spreadRoom[row][col] = 0;
						col--;
						direction = 0;
						break;
					}
					else spreadRoom[row][col] = spreadRoom[row][col - 1];
					col--;
				}
			}
		}
	}


	int sum = 0;
	for (int i = 0; i < r; i++) {
		for (int j = 0; j < c; j++) {
			sum += spreadRoom[i][j];
		}
	}
	cout << sum + 2 << endl;
	return 0;
}
728x90

'알고리즘 문제' 카테고리의 다른 글

[백준] 11050번 이항계수 1  (0) 2020.01.28
[백준] 1065번 한수  (0) 2020.01.28
[백준] 14891번 톱니바퀴  (0) 2020.01.27
[백준] 10809번 알파벳 찾기  (0) 2020.01.26
[백준] 14889번 스타트와 링크  (0) 2020.01.25

+ Recent posts