it 취업을 위한 알고리즘 문제풀이 입문 : 61. 특정 수 만들기(DFS : MS 인터뷰)
🙇♀️특정 수 만들기(DFS : MS 인터뷰)
N개의 원소로 구성된 자연수 집합이 주어지면, 집합의 원소와 ‘+’, ‘-’ 연산을 사용하여 특정 수인 M을 만드는 경우가 몇 가지 있는지 출력하는 프로그램을 작성하세요.
각 원소는 연산에 한 번만 사용합니다.
예를 들어 {2, 4, 6, 8}이 입력되고, M=12이면
2+4+6=12
4+8=12
6+8-2=12
2-4+6+8=12
로 총 4가지의 경우가 있습니다.
만들어지는 경우가 존재하지 않으면 -1를 출력한다.
▣ 입력설명
첫 번째 줄에 자연수 N(1<=N<=10)와 M(1<=M<=100) 주어집니다.
두 번째 줄에 집합의 원소 N개가 주어진다. 각 원소는 중복되지 않는다.
▣ 출력설명
첫 번째 줄에 “YES" 또는 ”NO"를 출력한다.
▣ 입력예제 1
4 12
2 4 6 8
▣ 출력예제 1
4
🚀풀이
내가 생각한 문제 풀이 접근법은 다음과 같다.
- 부분 집합을 모두 구한다. (DFS)
- 각 부분 집합마다
+, -
경우의 수를 모두 대입해 계산한다. (DFS) - 원하는 결과가 나올 때마다 카운트한다.
DFS로 부분집합을 계산한다면 그 부분집합에서도 또 DFS를 사용해 +, - 경우의 수를 세어야한다.
void DFS(int L)
{
if (L > n + 1)
return;
if (L == n + 1)
{
int cal = 0, cnt = 0;
vector<int> v;
for (int i = 1; i <= n; ++i)
{
if (ch[i] == 1)
{
v.push_back(arr[i]);
}
}
// 하나의 부분집합이 만들어졌으므로 다시 이경우에 대해서 DFS
DFS2(1, v);
v.clear();
}
ch[L] = 1;
DFS(L + 1);
ch[L] = 0;
DFS(L + 1);
}
void DFS2(int L, vector<int> vec)
{
if (L > vec.size() + 1)
return;
if (L == vec.size() + 1)
{
int cal = 0;
for (int i = 1; i <= vec.size(); ++i)
{
// +를 하는 경우
if (ch2[i] == 1)
{
cal += vec[i - 1];
}
// -를 하는 경우
else
{
cal -= vec[i - 1];
}
}
// 원하는 결과가 나왔을 때
if (cal == m)
{
res++;
}
}
ch2[L] = 1;
DFS2(L + 1, vec);
ch2[L] = 0;
DFS2(L + 1, vec);
}
어제 이 문제를 풀다가 생각이 안나서 오늘 다시 도전했다.
혼자 해결해서 다행인데 DFS속의 DFS이 머리가 복잡해져서 까다로운거같다.
강의를 보고 나의 코드와 비교해봐야겠다.
🚀강의를 보고 난 뒤..
강의에서는 배열의 값을 +로 넣을지 -로 넣을지 아예 넣지 않을지 이렇게 3가지 경우로 DFS를 만들었다.
나는 중첩된 DFS이지만 강의에서는 하나의 DFS로 풀 수 있었다.
강의 코드는 다음과 같다.
int n, m, res = 0;
int arr[11], ch[11];
void DFS(int L, int val)
{
if (L > n + 1)
return;
if (L == n + 1)
{
if (val == m)
res++;
}
DFS(L + 1, val + arr[L]);
DFS(L + 1, val - arr[L]);
DFS(L + 1, val);
}
나보다 더 간결하고 보기도 쉬워졌다… ㅠ
DFS문제는 아직 미숙해서 많이 풀어봐야겠다.
🚀전체 코드
// + - 집어 넣기
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include<iostream>
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
int n, m, res = 0, totalSum = 0;
int arr[11], ch[11], ch2[11];
void DFS2(int L, vector<int> vec)
{
if (L > vec.size() + 1)
return;
if (L == vec.size() + 1)
{
int cal = 0;
for (int i = 1; i <= vec.size(); ++i)
{
if (ch2[i] == 1)
{
cal += vec[i - 1];
}
else
{
cal -= vec[i - 1];
}
}
if (cal == m)
{
res++;
}
}
ch2[L] = 1;
DFS2(L + 1, vec);
ch2[L] = 0;
DFS2(L + 1, vec);
}
void DFS(int L)
{
if (L > n + 1)
return;
if (L == n + 1)
{
int cal = 0, cnt = 0;
vector<int> v;
for (int i = 1; i <= n; ++i)
{
if (ch[i] == 1)
{
v.push_back(arr[i]);
}
}
DFS2(1, v);
v.clear();
}
ch[L] = 1;
DFS(L + 1);
ch[L] = 0;
DFS(L + 1);
}
void solve()
{
cin >> n >> m;
for (int i = 1; i <= n; ++i)
{
cin >> arr[i];
totalSum += arr[i];
}
DFS(1);
cout << res;
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
//freopen("input.txt", "rt", stdin);
solve();
return 0;
}
강의 전체 코드
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include<iostream>
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
int n, m, res = 0;
int arr[11], ch[11];
void DFS(int L, int val)
{
if (L > n + 1)
return;
if (L == n + 1)
{
if (val == m)
res++;
}
DFS(L + 1, val + arr[L]);
DFS(L + 1, val - arr[L]);
DFS(L + 1, val);
}
void solve()
{
cin >> n >> m;
for (int i = 1; i <= n; ++i)
{
cin >> arr[i];
}
DFS(1, 0);
cout << res;
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
freopen("input.txt", "rt", stdin);
solve();
return 0;
}