문제 설명

1 로 색칠 된 크기가 가장 큰 정사각형의 크기를 구하면 된다.
1 칸은 1 이다.

풀이

정사각형의 조건 가로, 세로의 길이가 같다.

dp 를 이용해서 풀이하기 위해 맨 위부터 오른쪽으로 가면서 차례대로 밑으로 내려갔다.
현재의 위치에서 왼쪽의 길이와 세로의 길이가 같다면 최소한 맨 왼쪽 위를 제외하고 정사각형이 된다는 조건이다.
그러면 맨 왼쪽 위는 어떻게 검사하냐?
왼쪽 위의 대각선을 보면 된다.

결론적으로는 왼쪽, 위, 대각선 왼쪽 위 중 가장 작은 값 + 1를 해주면 된다.
그리고 넓이를 구하는 문제이니 제곱으로 출력해주면 된다. (정사각형 넓이)

코드

문제

n×m의 0, 1로 된 배열이 있다. 이 배열에서 1로 된 가장 큰 정사각형의 크기를 구하는 프로그램을 작성하시오.

0100
0111
1110
0010

위와 같은 예제에서는 가운데의 2×2 배열이 가장 큰 정사각형이다. 

입력

첫째 줄에 n, m(1 ≤ n, m ≤ 1,000)이 주어진다. 다음 n개의 줄에는 m개의 숫자로 배열이 주어진다.

출력

첫째 줄에 가장 큰 정사각형의 넓이를 출력한다.

예제 입력 1 

4 4
0100
0111
1110
0010

예제 출력 1 

4


문제 설명

1. LIS 의 기본문제
2. LIS 는 가장 긴 증가하는 부분수열을 구하는 알고리즘이다.

풀이

dp 와 arr 배열을 둬서 그 전의 박스들을 모두 확인한다.
1. dp 배열에는 현재 그 박스위치에서 가장 많은 박스의 개수를 저장하고
2. arr 배열에서는 박스의 크기를 저장한다.
3. arr[현재 박스위치] > arr[이전의 박스 모두들] 을 해서 가장 높은 dp[이전의 박스 모두들] 를 골라 + 1 해준게 dp[현재 박스위치] 에 들어간다.

증명

1. dp[0] = 1
풀이의 3을 0 ~ N 까지 한게 증명의 설명이 되겠다.

코드

문제

정육면체 모양의 상자들이 일렬로 늘어서 있다. 상자들마다 크기가 주어져 있는데, 앞에 있는 상자의 크기가 뒤에 있는 상자의 크기보다 작으면, 앞에 있는 상자를 뒤에 있는 상자 안에 넣을 수가 있다. 예를 들어 앞에서부터 순서대로 크기가 (1, 5, 2, 3, 7)인 5개의 상자가 있다면, 크기 1인 상자를 크기 5인 상자에 넣고, 다시 이 상자들을 크기 7인 상자 안에 넣을 수 있다. 하지만 이렇게 상자를 넣을 수 있는 방법은 여러 가지가 있을 수 있다. 앞의 예에서 차례대로 크기가 1, 2, 3, 7인 상자들을 선택하면 총 4개의 상자가 한 개의 상자에 들어가게 된다.

상자들의 크기가 주어질 때, 한 번에 넣을 수 있는 최대의 상자 개수를 출력하는 프로그램을 작성하시오.

입력

파일의 첫 번째 줄은 상자의 개수 n (1≤n ≤1000)을 나타낸다. 두 번째 줄에는 각 상자들의 크기가 순서대로 주어진다.

출력

첫째 줄에 한 줄에 넣을 수 있는 최대의 상자 개수를 출력한다.

예제 입력 1 

8
1 6 2 5 7 3 5 6

예제 출력 1 

5


문제 설명

0, 0 에서 N - 1, N -1 로 가는 경우의 수를 모두 구하면 된다.
이동은 오른쪽 또는 아래로만 가능하다.

풀이, 증명

입력과 동시에 답을 구했다. O(N^2)
1. dp[0][0] 은 1 로 초기화 한다.
2. 0,0 에서 오른쪽 또는 아래로 갈 수 있다면 이동한 곳에 값을 dp[0][0] 을 넣어준다.
그러면 각각 1 이 들어가게 된다.
3. for loop 이 돌면서 2 번 0,0 에 i,j 를 대입해서 순서대로 실행하게 되면 마지막 dp[N-1][N-1] 에는 답이 들어가게 된다.
위로 또는 왼쪽으로 못가기 때문에 순서대로 for loop 을 돌면서 답을 구할 수 있다.
왜냐하면 미리 답을 넣어놓고 거기에 도착하는 순간은 모든 경로를 다 확인했기 때문이다. 오른쪽 또는 아래로 갈 수 있는것은 j, i 를 더한다는게 된다.

설명이 부족했지만 알아서 이해하시면 됩니다.

코드

문제

N×N 게임판에 수가 적혀져 있다. 이 게임의 목표는 가장 왼쪽 위 칸에서 가장 오른쪽 아래 칸으로 규칙에 맞게 점프를 해서 가는 것이다.

각 칸에 적혀있는 수는 현재 칸에서 갈 수 있는 거리를 의미한다. 반드시 오른쪽이나 아래쪽으로만 이동해야 한다. 0은 더 이상 진행을 막는 종착점이며, 항상 현재 칸에 적혀있는 수만큼 오른쪽이나 아래로 가야 한다. 한 번 점프를 할 때, 방향을 바꾸면 안된다. 즉, 한 칸에서 오른쪽으로 점프를 하거나, 아래로 점프를 하는 두 경우만 존재한다.

가장 왼쪽 위 칸에서 가장 오른쪽 아래 칸으로 규칙에 맞게 이동할 수 있는 경로의 개수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 게임 판의 크기 N (4 ≤ N ≤ 100)이 주어진다. 그 다음 N개 줄에는 각 칸에 적혀져 있는 수가 N개씩 주어진다. 칸에 적혀있는 수는 0보다 크거나 같고, 9보다 작거나 같은 정수이며, 가장 오른쪽 아래 칸에는 항상 0이 주어진다.

출력

가장 왼쪽 위 칸에서 가장 오른쪽 아래 칸으로 문제의 규칙에 맞게 갈 수 있는 경로의 개수를 출력한다. 경로의 개수는 263-1보다 작거나 같다.

예제 입력 1 

4
2 3 3 1
1 2 1 3
1 2 3 1
3 1 1 0

예제 출력 1 

3

힌트


문제 설명 

1. 어떤 수 N 이 있을 때, 그 N 을 만들 수 있는 제곱수들의 합의 최소 개수를 구하면 되는 문제다.

풀이

1. dp 로 풀었다. dp 완전탐색
dp[i] = 답
답 = 1 or dp[i - j * j] + dp[j * j] (1 <= j * j <= i)

증명

1. dp[2] = dp[1] + dp[1] 이다.
2. dp[3] = dp [1] + dp[2] 이다.
결론적으로는 각 단계에서 구해놨던 최적해를 이용해서 우리가 구하고자 하는 최적해를 구할 수 있다는 것이다.
만약 N 이 10이라고 가정하면 답은 2 일 것이다.
그런데 구하는 과정이 어떻게되냐?
dp[i - j * j] + dp[j * j] (1 <= j * j <= i) j 를 증가시키면서 값을 업데이트 해주는데 저 조건에 해당하는 값은 제일 높은 값은 j = 3 일 때 이다.
j = 3 일 때 dp[9] + dp[1] 이 되므로 i 가 N 까지 도달하면서 이미 구해놨던 답을 기반으로 구할 수 있다. dp[9] 는 3 * 3 이므로 1 로 변경한다.

코드

문제

어떤 자연수 N은 그보다 작거나 같은 제곱수들의 합으로 나타낼 수 있다. 예를 들어 11=32+12+12(3개 항)이다. 이런 표현방법은 여러 가지가 될 수 있는데, 11의 경우 11=22+22+12+12+12(5개 항)도 가능하다. 이 경우, 수학자 숌크라테스는 “11은 3개 항의 제곱수 합으로 표현할 수 있다.”라고 말한다. 또한 11은 그보다 적은 항의 제곱수 합으로 표현할 수 없으므로, 11을 그 합으로써 표현할 수 있는 제곱수 항의 최소 개수는 3이다.

주어진 자연수 N을 이렇게 제곱수들의 합으로 표현할 때에 그 항의 최소개수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 자연수 N이 주어진다. (1 ≤ N ≤ 100,000)

출력

주어진 자연수를 제곱수의 합으로 나타낼 때에 그 제곱수 항의 최소 개수를 출력한다.

예제 입력 1 

7

예제 출력 1 

4


문제 설명

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


문제 설명

1. (1,1) 에서 시작 오른쪽, 밑, 대각선 이동 가능
2. 대각선으로 가는 경우는 오른쪽 또는 밑을 거쳐서 가는것보다 학상 작거나 같다. (음수가없음)

풀이

1. M 길이의 줄이 N 개 있다고 생각하고 풀었다. (최단거리를 찾는 문제랑 같음(도로에서 갈림길))
2. 오른쪽으로 가는 최대값은 항상 최대니 밑으로 내려가는 경우를 구해야됐다.
3. 밑으로 가는 경우에서 최대값은 왼쪽에서 오거나 바로 위에서 오는 경우이다.
4. 그래서 max(dp 배열의 현재 위치, dp 배열의 현재 위치에서의 왼쪽) 을 구해주면 된다.

증명

1. dp[1] 은 항상 최대값이다. (아래로 가는 경우만 존재)
2. dp[i] 에는 왼쪽 혹은 위에서 내려온 경우가 최대값이 된다.
첫 번째 줄만 생각해보자
dp[2] 를 구해야 하는 경우 왼쪽에서 오는 경우면 항상 최대값이다.
두 번째 줄을 생각해보면, 
dp[1] 은 이전의 dp[1] 이 최대값이다. 그러면 dp[2] 도 최대값이 들어가게 된다. (dp[1] 을 구하는 방식이랑 똑같이 하게되면)

코드

문제

준규는 N×M 크기의 미로에 갇혀있다. 미로는 1×1크기의 방으로 나누어져 있고, 각 방에는 사탕이 놓여져 있다. 미로의 가장 왼쪽 윗 방은 (1, 1)이고, 가장 오른쪽 아랫 방은 (N, M)이다.

준규는 현재 (1, 1)에 있고, (N, M)으로 이동하려고 한다. 준규가 (r, c)에 있으면, (r+1, c), (r, c+1), (r+1, c+1)로 이동할 수 있고, 각 방을 방문할 때마다 방에 놓여져있는 사탕을 모두 가져갈 수 있다. 또, 미로 밖으로 나갈 수는 없다.

준규가 (N, M)으로 이동할 때, 가져올 수 있는 사탕 개수의 최대값을 구하시오.

입력

첫째 줄에 미로의 크기 N, M이 주어진다. (1 ≤ N, M ≤ 1,000)

둘째 줄부터 N개 줄에는 총 M개의 숫자가 주어지며, r번째 줄의 c번째 수는 (r, c)에 놓여져 있는 사탕의 개수이다. 사탕의 개수는 0보다 크거나 같고, 100보다 작거나 같다.

출력

첫째 줄에 준규가 (N, M)으로 이동할 때, 가져올 수 있는 사탕 개수를 출력한다.

예제 입력 1 

3 4
1 2 3 4
0 0 0 5
9 8 7 6

예제 출력 1 

31

예제 입력 2 

3 3
1 0 0
0 1 0
0 0 1

예제 출력 2 

3

예제 입력 3 

4 3
1 2 3
6 5 4
7 8 9
12 11 10

예제 출력 3 

47

출처


문제 설명

1. N 자리수의 양의 정수가 오름차순(같아도 오름차순으로 친다)으로 되는 경우의 수를 구하면 된다.

풀이

1. dp 배열을 만들어서 그 전의 구해놨던 값을 이용한다.
2. dp 배열은 2차원 배열이고, [N의 자리수][i 로 시작할 때의 경우의 수] 로 테이블이 구성된다.
3. N = 3 으로 예를 들어보면, 1XX 는 dp[N][1] = dp[N-1][9~1] 이다.

코드

문제

오르막 수는 수의 자리가 오름차순을 이루는 수를 말한다. 이 때, 인접한 수가 같아도 오름차순으로 친다.

예를 들어, 2234와 3678, 11119는 오르막 수이지만, 2232, 3676, 91111은 오르막 수가 아니다.

수의 길이 N이 주어졌을 때, 오르막 수의 개수를 구하는 프로그램을 작성하시오. 수는 0으로 시작할 수 있다.

입력

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

출력

첫째 줄에 길이가 N인 오르막 수의 개수를 10,007로 나눈 나머지를 출력한다.

예제 입력 1 

1

예제 출력 1 

10

예제 입력 2 

2

예제 출력 2 

55

예제 입력 3 

3

예제 출력 3 

220

출처


문제 설명

1. 스티커가 2줄로 있다.
2. 연속으로 사용하지 않고, 최대한 많이 점수를 획득하라

풀이

1. dp 로 풀고, bottom-up 방식으로 풀었다.
2. 사선으로 뽑거나 건너띄고 뽑거나

증명

1. dp[1][0] = stickers[1][0] 이 최대값이다. [0][0]도 마찬가지
2. dp[x][i] = 사선으로 뽑은거 + stickers[x][i] 또는 dp[x][i - 1] 중 큰 값을 넣게되면 그 당시에 최대값이 들어가게 된다.
3. 2 번을 반복해서 앞으로 점점 가다보면, 그 상황에서의 최대값을 계속 사용하기 때문에 확장시켜서 보면 결론적으로는 최대값이 들어가게 된다.

코드

문제

상근이의 여동생 상냥이는 문방구에서 스티커 2n개를 구매했다. 스티커는 그림 (a)와 같이 2행 n열로 배치되어 있다. 상냥이는 스티커를 이용해 책상을 꾸미려고 한다.

상냥이가 구매한 스티커의 품질은 매우 좋지 않다. 스티커 한 장을 떼면, 그 스티커와 변을 공유하는 스티커는 모두 찢어져서 사용할 수 없게 된다. 즉, 뗀 스티커의 왼쪽, 오른쪽, 위, 아래에 있는 스티커는 사용할 수 없게 된다.

모든 스티커를 붙일 수 없게된 상냥이는 각 스티커에 점수를 매기고, 점수의 합이 최대가 되게 스티커를 떼어내려고 한다. 먼저, 그림 (b)와 같이 각 스티커에 점수를 매겼다. 상냥이가 뗄 수 있는 스티커의 점수의 최대값을 구하는 프로그램을 작성하시오. 즉, 2n개의 스티커 중에서 점수의 합이 최대가 되면서 서로 변을 공유 하지 않는 스티커 집합을 구해야 한다.

위의 그림의 경우에 점수가 50, 50, 100, 60인 스티커를 고르면, 점수는 260이 되고 이 것이 최대 점수이다. 가장 높은 점수를 가지는 두 스티커 (100과 70)은 변을 공유하기 때문에, 동시에 뗄 수 없다.

입력

첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스의 첫째 줄에는 n (1 ≤ n ≤ 100,000)이 주어진다. 다음 두 줄에는 n개의 정수가 주어지며, 각 정수는 그 위치에 해당하는 스티커의 점수이다. 연속하는 두 정수 사이에는 빈 칸이 하나 있다. 점수는 0보다 크거나 같고, 100보다 작거나 같은 정수이다. 

출력

각 테스트 케이스 마다, 2n개의 스티커 중에서 두 변을 공유하지 않는 스티커 점수의 최대값을 출력한다.

예제 입력 1 

2
5
50 10 100 20 40
30 50 70 10 60
7
10 30 10 50 100 20 40
20 40 30 50 60 20 80

예제 출력 1 

260
290


문제 설명

1. 쉽게 설명하면 2차원 배열에서 [i][j] ~ [x][y] 까지의 합을 구해서 출력하면 되는 문제다.
2. 문제의 데이터가 약해서 naive 하게 풀어도 풀린다.
3. dp 를 이용하면 소요되는 시간을 최소화 시킬 수 있다.

풀이

1. dp 를 이용해서 풀이하는 방법이다.
2. dp[i][j] 를 0,0 ~ i,j 까지의 합이 들어간다고 생각하고 구현하면, 사각형으로 세 구역이 나눠질 수 있다.
3. 문제에서 구하라고 제시한 구역과 그것이 아닌구역(아닌 구역을 2개로 나누면 위, 옆이 된다.) 총 3개
4. 풀이 방법은 0,0 ~ i,j 즉 dp[i][j] 에 나머지 영역을 빼주는 방법이다.

증명

수학적 귀납법
1. dp[1][1] = 항상 n[1][1] 이다.
2. dp[i][j] = dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1] + n[i][j] 로 하면 중복된 구역이 중복이 아니게 되고, 나머지 구역들이 더해지게 된다.
3. (2) 로 구해진 dp 배열을 사용해서 (2) 방식으로 구역의 합을 구한다.

코드

문제

2차원 배열이 주어졌을 때 (i, j) 위치부터 (x, y) 위치까지에 저장되어 있는 수들의 합을 구하는 프로그램을 작성하시오. 배열의 (i, j) 위치는 i행 j열을 나타낸다.

입력

첫째 줄에 배열의 크기 N, M(1≤N, M≤300)이 주어진다. 다음 N개의 줄에는 M개의 정수로 배열이 주어진다. 그 다음 줄에는 합을 구할 부분의 개수 K(1≤K≤10,000)가 주어진다. 다음 K개의 줄에는 네 개의 정수로 i, j, x, y가 주어진다(i≤x, j≤y).

출력

K개의 줄에 순서대로 배열의 합을 출력한다. 배열의 합은 32bit-int 범위를 초과하지 않는다.

예제 입력 1 

2 3
1 2 4
8 16 32
3
1 1 2 3
1 2 1 2
1 3 2 3

예제 출력 1 

63
2
36

출처



    문제 설명

    1. 붕어빵 N 개로 최대 수익을 내면 된다.

    풀이

    1. P[i] 에는 붕어빵 i 개로 이루어진 세트의 가격이다.
    2. dp[i] 는 붕어빵 i 개를 팔 때의 최대 수익이다.
    3. dp[i] = max(dp[i], P[i] + dp[i - j]) 를 하면 된다. (3 개를 산다고 하면, (1, 1, 1), (2, 1) 을 비교하면 됨 (처음에 3개짜리를 넣어주면)
    4. i 개를 판매할 때의 최대 수익 + P[i - j] 를 순서대로 갱신해주면
    5. 1 -> 5 -> 6 -> 10
    6. 10 -> 20 -> 30 -> 40 -> 50
    7. 1 -> 2 -> 3 -> 4 -> 5 -> 8 -> 13 -> 21 -> 34 -> 55

    코드

    문제

    강남역에서 붕어빵 장사를 하고 있는 해빈이는 지금 붕어빵이 N개 남았다.

    해빈이는 적절히 붕어빵 세트 메뉴를 구성해서 붕어빵을 팔아서 얻을 수 있는 수익을 최대로 만드려고 한다. 붕어빵 세트 메뉴는 붕어빵을 묶어서 파는 것을 의미하고, 세트 메뉴의 가격은 이미 정해져 있다.

    붕어빵 i개로 이루어진 세트 메뉴의 가격은 Pi 원이다.

    붕어빵이 4개 남아 있고, 1개 팔 때의 가격이 1, 2개는 5, 3개는 6, 4개는 7인 경우에 해빈이가 얻을 수 있는 최대 수익은 10원이다. 2개, 2개로 붕어빵을 팔면 되기 때문이다.

    1개 팔 때의 가격이 5, 2개는 2, 3개는 8, 4개는 10 인 경우에는 20이 된다. 1개, 1개, 1개, 1개로 붕어빵을 팔면 되기 때문이다.

    마지막으로, 1개 팔 때의 가격이 3, 2개는 5, 3개는 15, 4개는 16인 경우에는 정답은 18이다. 붕어빵을 3개, 1개로 팔면 되기 때문이다.

    세트 메뉴의 가격이 주어졌을 때, 해빈이가 얻을 수 있는 최대 수익을 구하는 프로그램을 작성하시오.

    입력

    첫째 줄에 해빈이가 가지고 있는 붕어빵의 개수 N이 주어진다. (1 ≤ N ≤ 1,000)

    둘째 줄에는 Pi가 P1부터 PN까지 순서대로 주어진다. (1 ≤ Pi ≤ 10,000)

    출력

    해빈이가 얻을 수 있는 최대 수익을 출력한다.

    예제 입력 1 

    4
    1 5 6 7
    

    예제 출력 1 

    10
    

    예제 입력 2 

    5
    10 9 8 7 6
    

    예제 출력 2 

    50
    

    예제 입력 3 

    10
    1 1 2 3 5 8 13 21 34 55
    

    예제 출력 3 

    55
    

    예제 입력 4 

    10
    5 10 11 12 13 30 35 40 45 47
    

    예제 출력 4 

    50
    

    예제 입력 5 

    4
    5 2 8 10
    

    예제 출력 5 

    20
    

    예제 입력 6 

    4
    3 5 15 16
    

    예제 출력 6 

    18


    + Recent posts