-
08. 8차시 수업알고리즘/정올1차교육(17.7.12~17.8.14) 2017. 8. 2. 21:27반응형
01.cpp - 회전초밥
*제가 짠 소스가 아닙니다*
/*#include <stdio.h>#define MAX_DISH 3000001#define MAX_FISH 3001int dishes[MAX_DISH];int hash[MAX_FISH];int head_idx = 0, tail_idx = 0;int safe_increment(const unsigned int index, const unsigned int dish){//dishes에 필요한 인덱스가 범위를 넘어가지 않도록 한다return (index + 1) % dish;}int enqueue(const unsigned int current_num, const unsigned int dish){const unsigned int ret =(++hash[dishes[head_idx]] == 1) ? (current_num + 1) : (current_num);head_idx = safe_increment(head_idx, dish);return ret;}int dequeue(const unsigned int current_num, const unsigned int dish){const unsigned int ret =(--hash[dishes[tail_idx]] == 0) ? (current_num - 1) : (current_num);tail_idx = safe_increment(tail_idx, dish);return ret;}int main(){int n_dish, n_fish, k, coupon;int i, max = 1; //1은 최초에 쿠폰으로 1개 먹기 때문int enq = 0;scanf("%d %d %d %d", &n_dish, &n_fish, &k, &coupon);for(i = 0; i < n_dish; ++i){scanf("%d", &dishes[i]);}hash[coupon]++;for(i = 0; i < k; ++i){enq = enqueue(max, n_dish);max = (enq > max) ? enq : max ;}for(i = 0; i < n_dish - 1; ++i){int j;enq = enqueue(dequeue(enq, n_dish), n_dish);max = (enq > max) ? enq : max;}printf("%d", max);}*/02.cpp - binary search. 이진탐색
//binary search#include <stdio.h>#include <algorithm>using namespace std;int first, last;int arr[100001];int original[100001];int want_to_find;int N;int binary_search(){if(last<first) return -1;int middle=(last+first+1)/2;if(want_to_find==arr[middle]) return middle;else if(want_to_find<arr[middle]) last=middle-1;else first=middle+1;return binary_search();}int main(){scanf("%d", &N);last=N;int cnt=1;for(int i=1; i<=N; ++i){scanf("%d", &arr[i]);original[arr[i]]=cnt++;}puts("want to find(it need not to be sorted)");scanf("%d", &want_to_find);sort(arr, arr+N);printf("that's on %d index(starts from zero)", original[binary_search()]);}이진탐색입니다. 항상 정렬된 배열 기준으로 first부터 last까지의 값 중 중간값((first+last+1)/2)을 구해서 그 값이 want_to_find와 같으면 그 인덱스를 리턴, 그 중간값이 want_to_find보다 작으면 first를 중간값+1로 옮기고 그 반대면 last를 중간값-1로 옮긴 후 재귀 돌립니다.
숫자 맞추기 게임(up&down게임)의 공략이기도 한 이진탐색입니다.
선생님 : 숫자 1부터 100까지 중 내가 뭘생각하고있게? 숫자 말하면 그 숫자가 내가 생각한 숫자보다 높은지 낮은지만 알려줄게!
총 7번만 말하면 찾을 수 있겠죠
03.cpp - Lis algorithm <ver.1 : find temp's length>
//longest increasing subsequence//ver.1#include <stdio.h>int arr[100000];int temp[100000];int t_last=0;int first=0, last;int N;int upgraded_b_search(int target, int range_f, int range_l){if(range_f==range_l) return range_l;else if(range_f+1==range_l){return range_l;}int middle=(first+last+1)/2;if(temp[middle]==target) return middle;else if(temp[middle]>target){range_l=middle;last=middle-1;}else{range_f=middle;first=middle+1;}return upgraded_b_search(target, range_f, range_l);}void find_Lis_length(){for(int i=1; i<N; ++i){first=0;last=t_last;if(arr[i]>temp[t_last]){temp[++t_last]=arr[i];//printf("okay\n");}else{//printf("b_search : ");int d=upgraded_b_search(arr[i], 0, t_last);//printf("upgraded_b_search(arr[i], 0, t_last) : %d\n",d);temp[d]=arr[i];}//for(int i=0; i<t_last; ++i){// printf("%d ", temp[i]);//}//printf("\n");}return;}int main(){scanf("%d", &N);for(int i=0; i<N; ++i){scanf("%d", &arr[i]);}temp[0]=arr[0];find_Lis_length();printf("\n");for(int i=0; i<t_last+1; ++i){printf("%d ", temp[i]);}printf("\n");printf("length : %d", t_last+1);//index starts from zero. so +1.}LIS알고리즘 중 binary-search를 이용해서 temp의 길이를 구하는 코드입니다.
원래는 lower-bound를 이용해서 푸는게 정석이지만 lower-bound까지 구현하고 싶어서 이렇게 짜봤습니다.
우선 결론 : lower-bound씁시다
그럼 이제 설명하겠습니다.
<temp배열을 만드는 방법>
1. 준비물 : arr배열, binary-search 함수 등등
2. 로직을 설명드리겠습니다.
(1) temp[0]에 arr[0]을 대입합니다.
(2) arr[1]부터 arr[n]까지 temp의 가장 마지막 숫자와 비교합니다.
arr[i]가 temp[last]보다 크면 ++last에 arr[i]를 대입합니다.
그 반대면 temp에서 arr[i]보다 큰 최소의 수를 binaray search(이진탐색)을 이용해서 찾습니다. 그리고 그 수에 arr[i]를 대입합니다. 이때 last는 변하지 않습니다.
(3) 배열의 길이는 last+1입니다. (배열이 0부터 시작하기 때문에)
LIS에 대한 자세한 설명은 다음시간에 하겠습니다.
반응형'알고리즘 > 정올1차교육(17.7.12~17.8.14)' 카테고리의 다른 글
10. 10차시 수업 (0) 2017.08.07 09. 9차시 수업 (0) 2017.08.06 07. 7차시 수업 (0) 2017.07.31 06. 6차시 수업 (0) 2017.07.30 05. 5차시 수업 (0) 2017.07.27