문제

상근날드에서 가장 잘 팔리는 메뉴는 세트 메뉴이다. 주문할 때, 자신이 원하는 햄버거와 음료를 하나씩 골라, 세트로 구매하면, 가격의 합계에서 50원을 뺀 가격이 세트 메뉴의 가격이 된다.

햄버거는 총 3종류 상덕버거, 중덕버거, 하덕버거가 있고, 음료는 콜라와 사이다 두 종류가 있다.

햄버거와 음료의 가격이 주어졌을 때, 가장 싼 세트 메뉴의 가격을 출력하는 프로그램을 작성하시오.

입력

입력은 총 다섯 줄이다. 첫째 줄에는 상덕버거, 둘째 줄에는 중덕버거, 셋째 줄에는 하덕버거의 가격이 주어진다. 넷째 줄에는 콜라의 가격, 다섯째 줄에는 사이다의 가격이 주어진다. 모든 가격은 100원 이상, 2000원 이하이다.

출력

첫째 줄에 가장 싼 세트 메뉴의 가격을 출력한다.

예제 입력 1 

800
700
900
198
330

예제 출력 1 

848


문제 설명

1. 연산자 우선순위는 없고 순서대로 연산하는거다. (앞에서부터)
2. 잘 배치해서 최대값, 최소값을 구해주면 된다.

풀이

1. dfs (브루트포스) 를 사용해서 완전 탐색을 해본다.
2. 모든 경우의 수를 대입하게 되면 무조건 답을 구할 수 밖에 없다.

코드

문제

N개의 수로 이루어진 수열 A1, A2, ..., AN이 주어진다. 또, 수와 수 사이에 끼워넣을 수 있는 N-1개의 연산자가 주어진다. 연산자는 덧셈(+), 뺄셈(-), 곱셈(×), 나눗셈(÷)로만 이루어져 있다.

우리는 수와 수 사이에 연산자를 하나씩 넣어서, 수식을 하나 만들 수 있다. 이 때, 주어진 수의 순서를 바꾸면 안된다.

예를 들어, 6개의 수로 이루어진 수열이 1, 2, 3, 4, 5, 6이고, 주어진 연산자가 덧셈(+) 2개, 뺄셈(-) 1개, 곱셈(×) 1개, 나눗셈(÷) 1개인 경우에는 총 60가지의 식을 만들 수 있다. 예를 들어, 아래와 같은 식을 만들 수 있다.

  • 1+2+3-4×5÷6
  • 1÷2+3+4-5×6
  • 1+2÷3×4-5+6
  • 1÷2×3-4+5+6

식의 계산은 연산자 우선 순위를 무시하고 앞에서부터 진행해야 한다. 또, 나눗셈은 정수 나눗셈으로 몫만 취한다. 음수를 양수로 나눌 때는 C++14의 기준을 따른다. 즉 양수로 바꾼 뒤 몫을 취하고, 그 몫을 음수로 바꾼 것과 같다. 이에 따라서, 위의 식 4개의 결과를 계산해보면 아래와 같다.

  • 1+2+3-4×5÷6 = 1
  • 1÷2+3+4-5×6 = 12
  • 1+2÷3×4-5+6 = 5
  • 1÷2×3-4+5+6 = 7

N개의 수와 N-1개의 연산자가 주어졌을 때, 만들 수 있는 식의 결과가 최대인 것과 최소인 것을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 수의 개수 N(2 ≤ N ≤ 11)가 주어진다. 둘째 줄에는 A1, A2, ..., AN이 주어진다. (1 ≤ Ai ≤ 100) 셋째 줄에는 합이 N-1인 4개의 정수가 주어지는데, 차례대로 덧셈(+)의 개수, 뺄셈(-)의 개수, 곱셈(×)의 개수, 나눗셈(÷)의 개수이다. 

출력

첫째 줄에 만들 수 있는 식의 결과의 최대값을, 둘째 줄에는 최소값을 출력한다. 최대값과 최소값은 항상 -10억보다 크거나 같고, 10억보다 작거나 같은 결과가 나오는 입력만 주어진다. 또한, 앞에서 부터 계산했을 때, 중간에 계산되는 식의 결과도 항상 -10억보다 크거나 같고, 10억보다 작거나 같다.

예제 입력 1 

2
5 6
0 0 1 0

예제 출력 1 

30
30

예제 입력 2 

3
3 4 5
1 0 1 0

예제 출력 2 

35
17

예제 입력 3 

6
1 2 3 4 5 6
2 1 1 1

예제 출력 3 

54
-24

힌트

세 번째 예제의 경우에 다음과 같은 식이 최대값/최소값이 나온다.

  • 최대값: 1-2÷3+4+5×6
  • 최소값: 1+2+3÷4-5×6


문제 설명

1. 자른 나무의 길이가 M 이상일 때 H 의 최대값을 구하시오

풀이

1. 나무의 최대 길이를 구해서 이분 탐색을 돌린다.

증명

1. 이분 탐색으로 남은 길이를 계속 구하면서 길이가 더 작다면 right 의 끝을 중간 - 1 로 해준다. 그 다음 이분 탐색을 반복하면 된다.
2. 아니라면 반대로 쭉 돌린다.

코드

문제

상근이는 나무 M미터가 필요하다. 근처에 나무를 구입할 곳이 모두 망해버렸기 때문에, 정부에 벌목 허가를 요청했다. 정부는 상근이네 집 근처의 나무 한 줄에 대한 벌목 허가를 내주었고, 상근이는 새로 구입한 목재절단기을 이용해서 나무를 구할것이다.

목재절단기는 다음과 같이 동작한다. 먼저, 상근이는 절단기에 높이 H를 지정해야 한다. 높이를 지정하면 톱날이 땅으로부터 H미터 위로 올라간다. 그 다음, 한 줄에 연속해있는 나무를 모두 절단해버린다. 따라서, 높이가 H보다 큰 나무는 H 위의 부분이 잘릴 것이고, 낮은 나무는 잘리지 않을 것이다. 예를 들어, 한 줄에 연속해있는 나무의 높이가 20, 15, 10, 17이라고 하자. 상근이가 높이를 15로 지정했다면, 나무를 자른 뒤의 높이는 15, 15, 10, 15가 될 것이고, 상근이는 길이가 5인 나무와 2인 나무를 들고 집에 갈 것이다. (총 7미터를 집에 들고 간다)

상근이는 환경에 매우 관심이 많기 때문에, 나무를 필요한 만큼만 집으로 가져가려고 한다. 이 때, 적어도 M미터의 나무를 집에 가져가기 위해서 절단기에 설정할 수 있는 높이의 최대값을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 나무의 수 N과 상근이가 집으로 가져가려고 하는 나무의 길이 M이 주어진다. (1 ≤ N ≤ 1,000,000, 1 ≤ M ≤ 2,000,000,000)

둘째 줄에는 나무의 높이가 주어진다. 나무의 높이의 합은 항상 M을 넘기 때문에, 상근이는 집에 필요한 나무를 항상 가져갈 수 있다. 높이는 1,000,000,000보다 작거나 같은 양의 정수 또는 0이다.

출력

적어도 M미터의 나무를 집에 가져가기 위해서 절단기에 설정할 수 있는 높이의 최대값을 출력한다.

예제 입력 1 

4 7
20 15 10 17

예제 출력 1 

15


문제 설명

1. 사자는 상하좌우로 겹칠 수 없다.
2. 없는 경우의 수도 카운트를 센다.

풀이

1. dp 를 이용해 풀었다.
2. i 번째 칸에 사자가 없는 경우
3. i 번째 칸에 사자가 왼쪽에 있는 경우
4. i 번째 칸에 사자가 오른쪽에 있는 경우
5. 위의 3 가지를 이용해서 풀었다.

증명

1. 1 번째 에서는 경우의 수가 3가지다.(항상)
2. i (i >= 2) 번째 에는 i - 1 번 째에 저장된 값을 이용해서 구할 수 있다. 예를 들어 [i][0] 을 구한다 하면 이전거에서 다 가능하기 때문에 [i-1][0~2] 를 다 더해줄 수 있다. 이런 방법을 사용하면
3. i 를 증가시키면서 답을 구할 수 있다.

코드

문제

어떤 동물원에 가로로 두칸 세로로 N칸인 아래와 같은 우리가 있다.

이 동물원에는 사자들이 살고 있는데 사자들을 우리에 가둘 때, 가로로도 세로로도 붙어 있게 배치할 수는 없다. 이 동물원 조련사는 사자들의 배치 문제 때문에 골머리를 앓고 있다.

동물원 조련사의 머리가 아프지 않도록 우리가 2*N 배열에 사자를 배치하는 경우의 수가 몇 가지인지를 알아내는 프로그램을 작성해 주도록 하자. 사자를 한 마리도 배치하지 않는 경우도 하나의 경우의 수로 친다고 가정한다.

입력

첫째 줄에 우리의 크기 N(1≤N≤100,000)이 주어진다.

출력

첫째 줄에 사자를 배치하는 경우의 수를 9901로 나눈 나머지를 출력하여라.

예제 입력 1 

4

예제 출력 1 

41



'아무거나' 카테고리의 다른 글

11월 초대장 7개 배포합니다.  (21) 2017.11.27
BOJ 1919 등!  (0) 2017.11.12
BOJ 랭킹 2222위 달성  (0) 2017.10.19

문제 설명

1. 연속된 부분집합 수열에서의 합이 M 이 되면 된다.

풀이

1. 투 포인터를 사용했다.

증명

1. left right 가 인덱스를 저장해서 영역을 지정한다.
2. sum 이 더 크면 left 가 오른쪽으로 한 칸 오면서 빼고
3. 더 작으면 right 가 오른쪽으로 한 칸 가면서 더한다.
4. 반복하면 O(N)

코드

문제

N개의 수로 된 수열 A[1], A[2], …, A[N] 이 있다. 이 수열의 i번째 수부터 j번째 수까지의 합 A[i]+A[i+1]+…+A[j-1]+A[j]가 M이 되는 경우의 수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 N(1≤N≤10,000), M(1≤M≤300,000,000)이 주어진다. 다음 줄에는 A[1], A[2], …, A[N]이 공백으로 분리되어 주어진다. 각각의 A[x]는 30,000을 넘지 않는 자연수이다.

출력

첫째 줄에 경우의 수를 출력한다.

예제 입력 1 

4 2
1 1 1 1

예제 출력 1 

3

예제 입력 2 

10 5
1 2 3 4 2 5 3 1 1 2

예제 출력 2 

3


문제 설명 및 풀이

1. 3 * 2 일 때 만들 수 있는 경우 3 가지
2. 3 * 4 부터 2 * 2 를 추가할 수 있다. 그래서 2 가지 더해주고
3. 3 * 6 일 때 또 패턴 생기고 쭉 생김

증명

솔직히 증명은 못하겠다. (다른 블로그들을 참고했기 때문이다.)
1. 비트마스크로 구하고 DP 하는 방법도 있다한다. 그건 증명이 가능할듯

코드

문제

3×N 크기의 벽을 2×1, 1×2 크기의 타일로 채우는 경우의 수를 구해보자.

입력

첫째 줄에 N(1 ≤ N ≤ 30)이 주어진다.

출력

첫째 줄에 경우의 수를 출력한다.

예제 입력 1 

2

예제 출력 1 

3

힌트

아래 그림은 3×12 벽을 타일로 채운 예시이다.


문제 설명

1. 하이픈으로 나눠진 성(first name)이 존재한다.
2. 성의 첫 번째 글자들만 모아서 출력하면 된다.

풀이

1. StringTokenizer 로 하이픈 기준으로 잘라서 출력

코드

문제

KMP 알고리즘이 KMP인 이유는 이를 만든 사람의 성이 Knuth, Morris, Prett이기 때문이다. 이렇게 알고리즘에는 발견한 사람의 성을 따서 이름을 붙이는 경우가 많다.

또 다른 예로, 유명한 비대칭 암호화 알고리즘 RSA는 이를 만든 사람의 이름이 Rivest, Shamir, Adleman이다.

사람들은 이렇게 사람 성이 들어간 알고리즘을 두 가지 형태로 부른다.

  • 첫 번째는 성을 모두 쓰고, 이를 하이픈(-)으로 이어 붙인 것이다. 예를 들면, Knuth-Morris-Pratt이다. 이것을 긴 형태라고 부른다.
  • 두 번째로 짧은 형태는 만든 사람의 성의 첫글자만 따서 부르는 것이다. 예를 들면, KMP이다.

동혁이는 매일매일 자신이 한 일을 모두 메모장에 적어놓는다. 잠을 자기 전에, 오늘 하루 무엇을 했는지 되새겨보는 것으로 하루를 마감한다.

하루는 이 메모를 보던 중, 지금까지 긴 형태와 짧은 형태를 섞어서 적어논 것을 발견했다.

이렇게 긴 형태로 하루 일을 기록하다가는 메모장 가격이 부담되어 파산될 것이 뻔하기 때문에, 앞으로는 짧은 형태로 기록하려고 한다.

긴 형태의 알고리즘 이름이 주어졌을 때, 이를 짧은 형태로 바꾸어 출력하는 프로그램을 작성하시오.

입력

입력은 한 줄로 이루어져 있고, 최대 100글자의 영어 알파벳 대문자, 소문자, 그리고 하이픈 ('-', 아스키코드 45)로만 이루어져 있다. 첫번째 글자는 항상 대문자이다. 그리고, 하이픈 뒤에는 반드시 대문자이다. 그 외의 모든 문자는 모두 소문자이다.

출력

첫 줄에 짧은 형태 이름을 출력한다.

예제 입력 1 

Knuth-Morris-Pratt

예제 출력 1 

KMP



문제

  예제를 보고 별찍는 규칙을 유추한 뒤에 별을 찍어 보세요.

입력

  첫째 줄에 N (1<=N<=100) 주어진다.

출력

  첫째 줄부터 2*N-1번째  까지 차례대로 별을 출력한다.

예제 입력 1 

3

예제 출력 1 

  *
 **
***
 **
  *

출처


문제 설명

1. Mi 의 숫자가 N 에 존재하는지 출력하는 문제

풀이

1. 이분탐색을 사용하라고 문제 분류가 돼있지만, 더 빠른 풀이를 위해 BitSet 을 사용했다.
2. 이분탐색을 사용하면 O(MlgN + NlgN) 정렬하고 찾는 시간이고, BitSet 을 사용하면(N+M) 이다.
3. 메모리 제한도 높고, Mi 의 제한도 높지 않아서 쉽게 풀 수 있었다.
4. JAVA 로 약 680MS 로 정답이니 거의 엄청 빠른 퍼포먼스를 낼 수 있었다. (첫 제출은 790MS 정도였다. 이유는 숫자 + 문자열을 write 해줬기 때문이다. 변경된 것은 문자열로만 되게)

코드

문제

숫자 카드는 정수 하나가 적혀져 있는 카드이다. 상근이는 숫자 카드 N개를 가지고 있다. 숫자 M개가 주어졌을 때, 이 숫자가 적혀있는 숫자 카드를 상근이가 가지고 있는지 아닌지를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 상근이가 가지고 있는 숫자 카드의 개수 N (1 ≤ N ≤ 500,000)이가 주어진다. 둘째 줄에는 숫자 카드에 적혀있는 숫자가 주어진다. 숫자 카드에 적혀있는 숫자는 -10,000,000보다 크거나 같고, 10,000,000보다 작거나 같다. 두 숫자 카드에 같은 숫자가 적혀있는 경우는 없다.

셋째 줄에는 M (1 ≤ M ≤ 500,000)이 주어진다. 넷째 줄에는 상근이가 가지고 있는 숫자 카드인지 아닌지를 구해야 할 M개의 숫자가 주어지며, 이 숫자는 공백으로 구분되어져 있다. 이숫자도 -10,000,000보다 크거나 같고, 10,000,000보다 작거나 같다

출력

첫째 줄에 입력으로 주어진 M개의 숫자에 대해서, 각 숫자가 적힌 숫자 카드를 상근이가 가지고 있으면 1을, 아니면 0을 공백으로 구분해 출력한다.

예제 입력 1 

5
6 3 2 10 -10
8
10 9 -5 2 3 4 5 -10

예제 출력 1 

1 0 0 1 1 0 0 1

출처


+ Recent posts