https://www.acmicpc.net/problem/2529
문제의 조건
1. k 는 2보다 크거나 같고, 9보다 작거나 같다
2. k+1개의 숫자는 서로 다른 숫자이다
3. k개의 부등호에 맞는 값 중 최대값, 최소값을 구해야 한다
부등호에 '<=', '>=' 이 존재하고 서로 다른 숫자라는 조건이 없었다면, 경우의 수가 1e10 이 돼 TLE이 나겠지만,
서로 다른 k+1 개의 수를 찾기 때문에 (k+1)! 의 경우의 수만 찾으면 된다.
처음에는 재귀함수를 통해 백트랙킹으로 풀었다.
소스코드 (백트랙킹)
숫자가 최대 10개이므로 비트마스크로 사용한 숫자를 체크하며, 조건이 맞지 않으면 재귀를 탈출하고,
k+1 개의 숫자를 다 채우면 1을 리턴하면서 종료된다.
최솟값은 0부터 시작해서 찾아야하고, 최댓값은 9부터 시작해서 내려가며 찾아야하기 때문에
같은 재귀라도 반복문을 달리 사용해야하는 번거로움이 있었다.
#include<stdio.h> #include<vector> #include<algorithm> #include<string> using namespace std; typedef long long ll; int k; char karr[11]; string min_="", max_=""; bool inline chk(int a, char c, int b){ return c == '>' ? a>b : a<b; } string num(vector<int>& ans){ string s = ""; for(int i=0; i < ans.size(); i++){ s += ans[i] + '0'; } return s; } int solve(vector<int>& ans, int visited, int p, int ismax){ if(p == k) { return 1; } int cur = ans[p]; int init = ismax ? 9 : 0; int iter = ismax ? -1 : 1; int end = ismax ? -1 : 10; for(int pp1=init; pp1 != end; pp1+=iter){ if(visited & (1<<pp1)) continue; if(chk(cur, karr[p], pp1)){ ans.push_back(pp1); if(solve(ans, visited | (1<<pp1), p+1, ismax)) return 1; ans.pop_back(); } } return 0; } string solve_(int i, int ismax){ int visited = 0; vector<int>ans; ans.push_back(i); visited |= (1<<i); if(solve(ans, visited, 0, ismax)){ return num(ans); } return ""; } int main(){ scanf("%d", &k); for(int i=0;i<k;i++){ scanf(" %c", &karr[i]); } for(int i=0; i<10; i++){ min_ = solve_(i, 0); if(min_ != "") break; } for(int i=9; i>=0; i--){ max_ = solve_(i, 1); if(max_ != "") break; } printf("%s\n%s\n", max_.c_str(), min_.c_str()); return 0; }
풀다보니 최소값은 0~k 의 숫자, 최대값은 9~9-k 까지의 숫자만 사용하면 부등호를 만족하는 순서를 찾을 수 있기 때문에,
k 가 9인 경우 최대 10! 까지만 돌기 때문에 조합으로 풀 수 있겠다 생각됐다.
소스코드 (조합)
조합으로 푸니 코드가 깔끔해졌다.. 진작 이렇게 풀걸
처음부터 조합으로 풀 생각을 할 수 있도록 문제 해결 전략을 잘 세워야겠다..
#include<stdio.h> #include<algorithm> #include<vector> using namespace std; int k; char karr[10]; bool inline chk_(int a, char c, int b){ return c == '>' ? a>b : a<b; } int chk(vector<int>& cand){ for(int i=0; i<k; i++){ if(!chk_(cand[i], karr[i], cand[i+1])) return 0; } return 1; } int main(){ scanf("%d", &k); for(int i=0; i<k;i++) scanf(" %c", &karr[i]); vector<int> min_ = vector<int>(k+1), max_ = vector<int>(k+1); for(int i=0; i<=k; i++){ min_[i] = i; max_[i] = 9-i; } do{ if(chk(min_)) break; }while(next_permutation(min_.begin(), min_.end())); do{ if(chk(max_)) break; }while(prev_permutation(max_.begin(), max_.end())); for(int i=0; i<=k; i++) printf("%d",max_[i]); printf("\n"); for(int i=0; i<=k; i++) printf("%d",min_[i]); printf("\n"); return 0; }
'알고리즘 문제풀이' 카테고리의 다른 글
BOJ 14503 로봇 청소기 (0) | 2021.06.12 |
---|---|
BOJ 1969 DNA (0) | 2021.05.24 |
BOJ 17472 다리만들기 2 (0) | 2020.11.24 |
BOJ 1305 광고 (0) | 2020.09.24 |
BOJ 10826 피보나치 수 4 (0) | 2020.09.04 |