일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 1796
- RBT
- 적두트리
- dp
- tfjs
- WebRTC란
- REACT
- TDD란?
- 백준
- LOLIN D32
- 풀이
- 데이터 링크 계층
- 테스트주도개발
- ESP32
- 구슬탈출
- mediastream
- 페이지교체알고리즘
- c++
- 메모리계층
- 자료구조
- 9996
- 백준 2133
- OpenVidu
- Vite 사용 이유
- TDD
- stl
- 13459
- 2623
- 3XN 타일링
- 구현
- Today
- Total
그냥 블로그
[C++/백준] 11066 파일 합치기 본문
https://www.acmicpc.net/problem/11066
11066번: 파일 합치기
소설가인 김대전은 소설을 여러 장(chapter)으로 나누어 쓰는데, 각 장은 각각 다른 파일에 저장하곤 한다. 소설의 모든 장을 쓰고 나서는 각 장이 쓰여진 파일을 합쳐서 최종적으로 소설의 완성본
www.acmicpc.net
[문제요약]
40 30 30 50이 있을 때, 괄호를 어떻게 잘 쳐주냐의 문제다.
(((40+30)+30)+50) 쳐준다 할 때, 괄호 안에서 더해지고 나오는 값을 계속 기록했을 떄 최소가 되는 경우가 뭐냐
[문제 풀이]
처음 방식을 생각할 때 두 가지가 생각났다.
1) 완전 탐색 2) DP
사실, 완전 탐색으로 풀 수 있는 문제는 아니기 때문에 바로 버리고, DP 아니면 다른 방법 있는지 찾아봤으나...
=> 다른 방법 없음
=> 무조건 DP
사용한 방법은 인덱스를 기준으로 dp 처리를 해주는 것
idx | 0 | 1 | 2 | 3 |
value | 40 | 30 | 30 | 50 |
1) Sum[501][501] => 구간합
Sum[idx1][idx2] : idx1 ~ idx2 까지의 숫자 합
ex) [0][2] : 40 + 30 + 30
[2[[3] : 30 + 50
2) DP[501][501]
a. 길이가 1 인 경우
ex) DP[0][0] -> 더하기를 하지 않은 = 0
DP[1][1] = 0
DP[N][N] = 0...
b. 길이가 2인 경우
ex) DP[0][1] = Sum[0][0] + Sum[1][1] => Sum[0][1] + DP[0][0] + DP[1][1]
DP[i][i+1] = Sum[i][i] + Sum[i+1][i+1
c. 길이가 2 초과 ( 둘 중 최소 )
ex) DP[0][2] = DP[0][0] + DP[1][2]
DP[0][1] + DP[2][2] + Sum[0][2]
idx | 0 | 1 | 2 | 3 |
0 | 0 | 70 | 100 + min(70, 60) | |
1 | 0 | 60 | 110 + min(60, 80) | |
2 | 0 | 80 | ||
3 | 0 |
[풀이]
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int T;
int sum[501][501];
int DP[501][501];
int main() {
cin >> T;
for (int t = 0; t < T; t++) {
int N;
cin >> N;
fill(&DP[0][0], &DP[0][0] + 501 * 501, 2e9);
fill(&sum[0][0], &sum[0][0] + 501 * 501, 0);
for (int i = 0; i < N; i++) {
cin >> DP[i][i];
DP[i][i] = 0;
}
// 합을 구해주는 부분.
for (int s = 0; s < N-1; s++) {
for (int e = s + 1; e < N ;e++) {
for (int i = s; i <= e;i++)
sum[s][e] += sum[i][i];
}
}
// l : idx1 ~ idx2 까지의 길이
// s : 시작 idx1
// m : s ~ s+l (idx1 ~ idx2) 중간 지점을 두고 돌아가면서 최소를 구한다.
for (int l = 1; l < N; l++) {
for (int s = 0; s < N - l; s++) {
for (int m = 0; m < l; m++) {
DP[s][s + l] = min(DP[s][s + l], DP[s][s + m] + DP[s + m + 1][s + l]+sum[s][s+l]);
}
}
}
cout << DP[0][N - 1] << '\n';
}
}
'C++ > 백준' 카테고리의 다른 글
[C++/백준] 흙길 보수하기 (0) | 2024.07.07 |
---|---|
[C++/백준] 1486 등산 (0) | 2024.05.12 |
[C++/백준] 16434 드래곤 앤 던전 (1) | 2024.04.07 |
[C++/백준] 16637 괄호 추가하기 (1) | 2024.03.24 |
[C++ / 백준] 2133 타일 채우기 (0) | 2024.03.23 |