반응형
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- BOJ
- Docker
- 오퍼레터
- BFS
- 물채우기
- 기술면접
- Kafka
- boj #19237 #어른 상어
- 13908
- 퇴사통보
- incr
- 백준
- upper_bound
- 이분탐색
- 백트래킹
- 경력
- 처우협의
- 성적평가
- @P0
- OFFSET
- msSQL
- 6987
- 매개변수탐색
- 연결요소
- 파라메트릭
- dfs
- 소프티어
- 처우산정
- compose
- softeer
Archives
- Today
- Total
기술 블로그
16508번 전공책 본문
728x90
반응형
https://www.acmicpc.net/problem/16508
백트래킹 문제라고 생각하였으나, 잘 접근하지 못 하였다.
그래서 그냥 단순 구현으로 작성해보았으나, 반례가 있어서 잘 안 풀렸다.
맨 아래가 코드가 내가 작성한 코드이다.(틀린 코드임.)
그래서 다른 분의 코드를 보았더니, 역시 백트래킹으로도 풀 수 있는 문제였다.
백트래킹에 대해 더 열심히 해야겠다.
참고로, 해당 문자의 '개수'가 중요한 것이었다.
순서는 아래처럼 작성하여도 된다.
1 2 3 4 5 6 7 | used[pos] = true; sum += cost[pos]; BackTracking(pos + 1); used[pos] = false; sum -= cost[pos]; BackTracking(pos + 1); | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | #include <iostream> #include <queue> #include <stack> #include <cstdio> #include <vector> #include <cstring> #include <string> #include <math.h> #include <algorithm> #include <map> using namespace std; int INF, result; int N = 0, sum = 0; int letter[26] = { 0, }; // 원하는 단어에 대한 해당 문자 개수 int cost[16] = { 0, }; // 전공책 가격 int book[16][26] = { 0, }; // [a][b] : a 번째 책에 해당하는 책 이름에 대한 해당 문자 개수 int cnt[26] = { 0, }; bool used[16] = { false, }; // 책 사용 여부 void BackTracking(int pos) { if (pos == N) { memset(cnt, 0, sizeof(cnt)); for (int i = 0; i < N; i++) { if (!used[i]) continue; for (int j = 0; j < 26; j++) { cnt[j] += book[i][j]; } } for (int i = 0; i < 26; i++) { if (cnt[i] < letter[i]) return; // 내가 원하는 어떤 단어의 해당하는 문자의 개수가 더 많다면, // 이 원하는 단어를 만들 수 없는 경우이므로, return } result = min(result, sum); return; } BackTracking(pos + 1); used[pos] = true; sum += cost[pos]; BackTracking(pos + 1); used[pos] = false; sum -= cost[pos]; } int main(void) { INF = INT32_MAX; result = INF; string T; cin >> T; for (int i = 0; i < T.length(); i++) { ++letter[T[i] - 'A']; } scanf("%d", &N); int C = 0; string W; for (int i = 0; i < N; i++) { cin >> C >> W; cost[i] = C; for (int j = 0; j < W.length(); j++) { ++book[i][W[j] - 'A']; } } BackTracking(0); if (result == INF) printf("-1\n"); else printf("%d\n", result); return 0; } | cs |
<내가 작성한 코드. 틀린 코드이다.>
반례
AB
3
10 A
15 B
10 B
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | #include <iostream> #include <queue> #include <stack> #include <cstdio> #include <vector> #include <cstring> #include <string> #include <math.h> #include <algorithm> #include <map> using namespace std; typedef struct Book { int money; string name; }Book; string Word; int N = 0; vector<Book> v; bool isUsedBook[20] = { false, }; bool isUsedChar[20] = { false, }; int main(void) { int bookMoney = 0, result = 987654321; bool isCalc = false; string bookTitle; cin >> Word; int wordSize = Word.size(); cin >> N; Book book; for (int i = 0; i < N; i++) { cin >> bookMoney >> bookTitle; book.money = bookMoney; book.name = bookTitle; v.push_back(book); } int index = 0; int Count = N; bool isCheck[20][55] = { false, }; memset(isCheck, false, sizeof(isCheck)); while (Count--) { for (int i = index; i < N; i++) { string s = v.at(i).name; int sSize = s.size(); for (int j = 0; j < wordSize; j++) { for (int k = 0; k < sSize; k++) { if (Word[j] == s[k]) { if (isUsedChar[j] || isCheck[i][k]) continue; // 이미 원하는 단어 안의 '문자'를 검사했거나 입력한 책의 제목 안의 '문자'가 검사를 당했다면, 무시한다. // 인덱스로 검사, 사용 여부를 판별한다. 0 ~ isCheck[i][k] = true; // i번 째 책의 k번 째 '문자' 사용 여부 isUsedBook[i] = true; // i번 째 책의 사용 여부 isUsedChar[j] = true; // 입력한 원하는 단어의 j번 째 '문자' 사용 여부 break; } } } int Length = 0; for (int j = 0; j < wordSize; j++) { if (isUsedChar[j]) { // 원하는 단어에서 사용된 문자라면, Length 증가 ++Length; } } // 그 Length가 원하는 단어의 길이와 같다면 if (Length == wordSize) { int caseSumMoney = 0; isCalc = true; // 계산 여부 표시 for (int j = 0; j < N; j++) { if (isUsedBook[j]) { // j번 째 책이 사용되었다면 caseSumMoney += v.at(j).money; // 돈 적립 } } result = min(result, caseSumMoney); // 최솟값을 구한다. memset(isUsedBook, false, sizeof(isUsedBook)); memset(isUsedChar, false, sizeof(isUsedChar)); memset(isCheck, false, sizeof(isCheck)); // 한 번 계산 완료하였으니, 다음 번 계산을 위해 모두 초기화 한다. break; // 한 번의 계산이 완료된다면, 다음 순서에 있는 책에 대한 기준으로 넘어간다. } } ++index; // 따라서, index가 1 증가한다. 동시에, Count는 1 감소한다.(while문 조건) } if(isCalc) cout << result << '\n'; else cout << "-1\n"; // 계산을 한 적이 없다면, -1 출력 return 0; } | cs |
728x90
반응형
'알고리즘 문제 > BOJ' 카테고리의 다른 글
16561번 3의 배수 (0) | 2018.11.24 |
---|---|
16507번 어두운 건 무서워 (0) | 2018.11.23 |
16509번 장군 (0) | 2018.11.21 |
16510번 Predictable Queue (0) | 2018.11.21 |
16504번 종이접기 (0) | 2018.11.19 |