[예제1] BOJ 1182 부분수열의 합
https://www.acmicpc.net/problem/1182
N개의 정수로 이루어진 수열이 있을 때, 크기가 양수인 부분수열 중에서 그 수열의 원소를 다 더한 값이 S가 되는 경우의 수를 구하는 프로그램을 작성하시오.
브루트포스로 풀었을 때.
백트래킹보다 느리고 메모리 사용량이 많다.
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int N, S;
cin >> N >> S;
vector<int> v(N);
vector<vector<int>> sums(N);
for (int i = 0; i < N; i++)
cin >> v[i];
sums[0].push_back(v[0]);
int answer = 0;
if (v[0] == S)answer++;
for (int i = 1; i < N; i++)
{
sums[i].push_back(v[i]);
if (v[i] == S)
answer++;
for (int j = 0; j < i; j++)
{
for (int prev : sums[j])
{
if (prev + v[i] == S)
answer++;
sums[i].push_back(prev + v[i]);
}
}
}
cout << answer;
}
백트래킹으로 풀었을 때.
코드가 더 직관적으로 효율적이다.
각 원소마다 선택/미선택 2분기이므로, 시간복잡도는 O(2^N) 이다.
int N, S;
int answer = 0;
void BackTracking(vector<int>& nums, int sum, int i)
{
if (i >= N)
return;
if (sum + nums[i] == S)
answer++;
BackTracking(nums, sum, i + 1);
BackTracking(nums, sum + nums[i], i + 1);
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cin >> N >> S;
vector<int> v(N);
for (int i = 0; i < N; i++)
cin >> v[i];
BackTracking(v, 0, 0);
cout << answer;
}
[예제2] BOJ 14888 연산자 끼워넣기
여기까지 풀고 백트래킹 쉽고 재밌다고 생각했다...
int N;
vector<int> nums;
int addC, subC, mulC, divC;
int minResult = 1000000000;
int maxResult = -1000000000;
void BackTracking(int i, int result, int leftAddC, int leftSubC, int leftMulC, int leftDivC)
{
if (i == N)
{
minResult = min(minResult, result);
maxResult = max(maxResult, result);
return;
}
if (leftAddC > 0)
BackTracking(i + 1, result + nums[i], leftAddC - 1, leftSubC, leftMulC, leftDivC);
if (leftSubC > 0)
BackTracking(i + 1, result - nums[i], leftAddC, leftSubC - 1, leftMulC, leftDivC);
if (leftMulC > 0)
BackTracking(i + 1, result * nums[i], leftAddC, leftSubC, leftMulC - 1, leftDivC);
if (leftDivC > 0)
BackTracking(i + 1, result / nums[i], leftAddC, leftSubC, leftMulC, leftDivC - 1);
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cin >> N;
nums = vector<int>(N);
for (int i = 0; i < N; i++)
cin >> nums[i];
cin >> addC >> subC >> mulC >> divC;
BackTracking(1, nums[0], addC, subC, mulC, divC);
cout << maxResult << '\n' << minResult;
}
[예제3] BOJ 9663 N-Queen
https://www.acmicpc.net/problem/9663
N-Queen 문제는 크기가 N × N인 체스판 위에 퀸 N개를 서로 공격할 수 없게 놓는 문제이다.
N이 주어졌을 때, 퀸을 놓는 방법의 수를 구하는 프로그램을 작성하시오.
체스에서 퀸은 상하좌우, 대각선으로 이동 가능하다.
간단하게 풀 수 있는 아이디어는, 한 행에 1개씩만 놓을 수 있다는 것을 이용하는 것.
그리고 같은 열이나 대각선에 퀸이 있는지 조건을 검사하면 된다.
void BackTracking(vector<vector<bool>> v, int y, int x, int count)
{
...
if (possible && y + 1 < N)
{
v[y][x] = true;
BackTracking(v, y + 1, 0, count + 1);
}
if(x + 1 < N)
{
v[y][x] = false;
BackTracking(v, y, x + 1, count);
}
}
처음에 이런 구조로 했다가 chatGPT한데 호되게 혼났다. 아직도 이해를 못했다. 내일 다시 풀어볼 것임 ㅠㅠ
'공부 잡동사니 > 알고리즘' 카테고리의 다른 글
[알고리즘] 위상 정렬 (0) | 2025.05.15 |
---|---|
[알고리즘] Union-Find와 사이클 판별&크루스칼 알고리즘 (0) | 2025.05.15 |
[알고리즘] BOJ 16947 서울 지하철 2호선 (DFS + BFS+ 백트래킹) (0) | 2025.05.08 |
[알고리즘] 투 포인터(Two Pointer) (0) | 2025.05.07 |
댓글