https://www.acmicpc.net/problem/5568
5568번: 카드 놓기
문제 상근이는 카드 n(4 ≤ n ≤ 10)장을 바닥에 나란히 놓고 놀고있다. 각 카드에는 1이상 99이하의 정수가 적혀져 있다. 상근이는 이 카드 중에서 k(2 ≤ k ≤ 4)장을 선택하고, 가로로 나란히 정수를 만들기로 했다. 상근이가 만들 수 있는 정수는 모두 몇 가지일까? 예를 들어, 카드가 5장 있고, 카드에 쓰여 있는 수가 1, 2, 3, 13, 21라고 하자. 여기서 3장을 선택해서 정수를 만들려고 한다. 2, 1, 13을 순서대로 나열하면
www.acmicpc.net
조합, 중복조합, 중복순열은 구현하였는데 순열 만큼은 직접 구현해본 경험이 없었다. 그래서 순열을 직접 구현하였다. set을 이용하여 중복된 원소를 거르고 숫자의 순서가 바뀌면 다른 수로 인식하도록 하였다.
#include <iostream>
#include <vector>
#include <string>
#include <set>
#include <algorithm>
using namespace std;
vector<int> v; //입력한 숫자
vector<bool> visit; //방문 여부
vector<int> selects; //뽑은 숫자
set<string> st; //만들어진 숫자들
int m, n; //m개의 숫자 중 n개를 뽑는다.
//순열 구현
void per(int depth) {
if (depth == n) { //원하는 수 만큼 뽑으면
string s; //완성된 숫자
string change; //이어붙일 숫자
for (int i = 0; i < selects.size(); i++) { //선택한 숫자를 이어붙인다.
change = to_string(selects[i]);
s = s + change;
}
st.insert(s); //만든 숫자 삽입
return;
}
for (int i = 0; i < m; i++) { //중복이 허용되므로 항상 0번째부터 탐색
if (visit[i]) { //방문한 곳이면
continue; //무시
}
visit[i] = true; //현재 원소 방문처리
selects.push_back(v[i]); //현재 뽑은 원소를 저장
per(depth + 1); //재귀로 다시 재탐색
visit[i] = false; //현재 원소 미방문처리
selects.pop_back(); //현재 뽑은 원소를 삭제
}
}
int main() {
cin >> m;
cin >> n;
//m개의 숫자를 삽입
for (int i = 0; i < m; i++) {
int num;
cin >> num;
v.push_back(num);
visit.push_back(false);
}
per(0); //순열 실행
cout << st.size(); //만들 수 있는 숫자의 갯수 출력
}
'백준' 카테고리의 다른 글
백준17224 - APC는 왜 서브태스크 대회가 되었을까? (0) | 2019.09.01 |
---|---|
백준1747 - 소수&팰린드롬 (0) | 2019.08.31 |
백준1350 - 진짜 공간 (0) | 2019.08.30 |
백준1932 - 정수 삼각형 (0) | 2019.08.29 |
백준15651 - N과 M (3) (0) | 2019.08.27 |