본문 바로가기

Algorithm/DFS

(C++) - 백준(BOJ) 15663번 : N과 M (9)

반응형

https://www.acmicpc.net/problem/15663

 

15663번: N과 M (9)

한 줄에 하나씩 문제의 조건을 만족하는 수열을 출력한다. 중복되는 수열을 여러 번 출력하면 안되며, 각 수열은 공백으로 구분해서 출력해야 한다. 수열은 사전 순으로 증가하는 순서로 출력해야 한다.

www.acmicpc.net

backtracking 문제였습니다.

 

풀이방법

 1. set을 사용하는 방법

 2. 사용하지 않고 level별로 체크하는 배열을 하나 더 두어 중복을 방지하는 방법

 

Code

1. set사용

#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
using namespace std;
int n, m;
int a[8];
int ck[8];
int tmp[8];
set<vector<int>> ans;
//중복 저장을 하지 않는 set이용
void DFS(int level)
{
    if (level == m)
    {
        vector<int> v;
        for (int i = 0; i < m; i++)
            v.push_back(tmp[i]);
        //set에 무조건 때려박는다
        ans.insert(v);
        v.clear();
        return;
    }
    for (int i = 0; i < n; i++)
    {    
        if (ck[i] == 0)
        {
            ck[i] = 1;
            tmp[level] = a[i];
            DFS(level + 1);
            ck[i] = 0;
        }
    }
}
int main() {
    cin >> n >> m;
    for (int i = 0; i < n; i++)
    {
        cin >> a[i];
    }
    sort(a, a + n);//정렬
    DFS(0);

    for (auto a : ans)
    {
        for (int i = 0; i < a.size(); i++)
        {
            cout << a[i] << ' ';
        }
        cout << '\n';
    }
}

 

2. 다른 방법

#include <bits/stdc++.h>
using namespace std;
int n,m;
vector<int> num, v;
int ck2[10001][10];
int ck[10001];
void backtracking(int depth){
    if(depth == m){
        for(int i = 0; i < m; i++){
            cout << v[i] << ' ';
        }
        cout << '\n';
        return;
    }

    for(int i = 0; i < n; i++){
        if(ck[i] || ck2[num[i]][depth]) continue;
        ck[i] = 1;
        ck2[num[i]][depth] = 1;
        v.push_back(num[i]);
        dfs(depth + 1);
        v.pop_back();
        ck[i] = 0;
    }

    for(int i = 0; i < n; i++){
        ck2[num[i]][depth] = 0;
    }
}

int main(){
    cin >> n >> m;
    for(int i = 0,x; i < n; i++){
        cin >> x;
        num.push_back(x);
    }
    sort(num.begin(),num.end());
    dfs(0);
}