for Robot Artificial Inteligence

다이나믹 프로그래밍 컴퓨터 공학적 사고를 위한 이해2

|

동적 계획법(Dynamic Programming, DP)은 큰 문제를 작은 문제로 나누어서 푸는 방식의 알고리즘이다. 동적 계획법은 처음 주어진 문제를 더 작은 문제들로 나눈 뒤 각 조각의 답을 계산하고, 이 답들로부터 원래 문제에 대한 답을 계산해 낸다는 점에서 분할 정복(Divide & Conquer, D&C)과 비슷하다. 하지만 가장 큰 차이점은 동적 계획법에서는 쪼개진 작은 문제가 중복되지만, 분할 정복은 절대로 중복될수가 없다는 점이다.

다시 말하면, 동적 계획법과 분할 정복의 차이는 문제를 나누는 방식이다. 동적 계획법에서는 어떤 부분 문제는 두 개 이상의 문제를 푸는데 사용될 수 있기 때문에, 이 문제의 답을 여러 번 계산하는 대신 한 번만 계산하고 그 결과를 재활용함으로써 속도의 향상을 시킬 수 있다. 이때 이미 계산한 값을 저장해 두는 메모리를 캐시(cache)라고 부르며, 두 번 이상 계산되는 부분 문제를 중복되는 부분 문제(overlapping subproblems)라고 부른다.

1. 동적 계획법의 조건

  • 두 가지 속성을 만족해야 동적 계획법으로 문제를 풀 수 있다.
    • Overlapping Subproblem : 겹치는 부분(작은) 문제
    • Optimal Substructure : 최적 부분구조

2.Memoization

동적 계획법에서 각 문제는 한 번만 풀어야 한다. 중복되는 부분 문제를 여러번 풀지 않는다는 뜻이다. Optimal Substructure를 만족하기 때문에 같은 문제는 구할 때마다 정답이 같다. 따라서 정답을 한 번 구했으면 그 정답을 캐시에 메모해놓는다. 이렇게 메모하는 것을 코드의 구현에서는 배열에 저장하는 것으로 할 수 있다. 이를 메모이제이션(Memoization)이라고 한다.

int fibonacci(int n) {
    if (n <= 1) {	// F(0) = 0, F(1) = 1
        return n;
    } else {
	return fibonacci(n-1) + fibonacci(n-2);
    }
}

이런식을 구현하면 될텐데, 여기에서 이미 계산한 부분문제의 경우 그 값을 그대로 사용하는 코드를 추가해야 한다. memo배열에 값이 0이면 답을 구하지 않았다는 뜻이고, 0이 아니면 답을 구한적이 있다(이전의 호출에서 해당 값을 구함)는 뜻이므로, 이를 활용하면 된다.

int memo[100];
int fibonacci(int n) {
    if (n <= 1) {
    	return n;
    } else {
        if (memo[n] > 0) {	// memo의 값이 0이 아니면
            return memo[n];	// 그 값을 그대로 사용
        }
        memo[n] = fibonacci(n-1) + fibonacci(n-2);
        return memo[n];
    }
}

3.동적 계획법 구현 방식

  1. Top-down : 큰 문제를 작은 문제로 쪼개면서 푼다. 재귀로 구현
      1. 큰 문제를 작은 문제로 나눈다.
      1. 작은 문제를 푼다.
      1. 작은 문제를 풀었으니, 이제 큰 문제를 푼다.

피보나치 문제로 예를 들면, fibonacci(n)라는 문제를 풀기위해서 문제를 작은 문제로 나눈다.

  • fibonacci(n-1)과 fibonacci(n-2)로 문제를 나눈다. 작은 문제를 푼다.
  • fibonacci(n-1)과 fibonacci(n-2)를 호출해 문제를 푼다. 작은 문제를 풀었으니, 이제 문제를 푼다.
  • fibonacci(n-1)의 값과 fibonacci(n-2)의 값을 더해 문제를 푼다.
  1. Bottom-up : 작은 문제부터 차례대로 푼다. 반복문으로 구현
    • 1.문제를 크기가 작은 문제부터 차례대로 푼다.
    • 2.문제의 크기를 조금씩 크게 만들면서 문제를 점점 푼다.
    • 3.작은 문제를 풀면서 왔기 때문에, 큰 문제는 항상 풀 수 있다.
    • 4.반복하다 보면 가장 큰 문제를 풀 수 있다.

똑같이 피보나치 문제로 예를 들면,

문제를 크기가 작은 문제부터 차례대로 푼다.

  • for (int i=2; i<=n; i++) 문제의 크기를 조금씩 크게 만들면서 문제를 점점 푼다.
  • for (int i=2; i<=n; i++) 작은 문제를 풀면서 왔기 때문에, 큰 문제는 항상 풀 수 있다.
  • d[i] = d[i-1] + d[i-2]; 반복하다 보면 가장 큰 문제를 풀 수 있다.
  • d[n]을 구하게 된다.
int d[100];
int fibonacci(int n) {
    d[0] = 0;
    d[1] = 1;
    for (int i=2; i<=n; i++) {	// 2에서 부터 시작해서 n까지 반복
    	d[i] = d[i-1] + d[i-2];
    }
    return d[n];
}

Comment  Read more

다이나믹 프로그래밍 컴퓨터 공학적 사고를 위한 이해

|

다이나믹 프로그래밍은 동적 계획법이라 말한다.

다이나믹 프로그래밍은 문제가 다음 조건을 만족할 때 사용할 수 있다.(중요)

  1. 최적 부분 구조(Optimal Substructure)
    • 큰 문제를 작은 문제로 나눌 수 있으며 작은 문제의 답을 모아 큰 문제를 해결 할 수 있는 것
  2. 중복되는 부분 문제(Overlapping Subproblem)
    • 동일한 작은 문제를 반복적으로 해결해야 한다.

탑다운 방식 같은 경우 재귀함수를 사용한다. 다운탑 방식 같은 경우 loop 함수를 사용한다.

메모이제이션 동작 분석

문제 1

문제 2

문제 3

문제 4

문제 5

Comment  Read more

그리드 알고리즘 언제 쯤 사용?

|

  • 현재 상황에서 가장 좋아보이는 답을 선택한다.
  • 각 부분에서 최적을 선택하면 전체에서 최적이 될 것이라는 가정을 전제로 한다.
  • 기본적으로 값이 큰 경우대로 극단적으로 문제를 접근한다.

예제

  1. 분할 가능 배낭 문제
    • 여행가가 가지고 있는 배낭에는 담을 수 있는 무게의 최대값이 정해져있고, 일정 가치와 무게가 있는 짐들을 배낭을 넣을 때 가치의 합이 최대가 되도록 짐을 고르는 문제
  2. 최소수의 동전으로 거스름돈 내주기
    • 거스름돈을 내줄때 가장 적은 양의 동전을 내주는 문제
    • 예) 930원의 거스름돈을, 500원, 200원, 50원, 10원의 동전으로 내줄때, 500원 동전 1개 + 200원 동전 2개+ 10원 동전 3개 총 6개의 동전으로 가장 적은 양의 동전을 내줄 수 있다.

다이나믹 프로그래밍을 써야할 경우

위에 나온 예제를 이용하여서

930원의 거스름돈을 500원, 300원, 30원, 10원의 동전으로 동전의 단위가 바뀌었을 경우,

그리드 방법을 사용하여서 풀었을때

500원 동전 1개 + 300원 동전 1개 + 30원 동전 4개 + 10원 동전 1개 = 총 7개 이지만

300원 동전 3개 + 30원 동전 1개 = 총 4개의 더 작은 동전의 양으로 내줄 수 있다.

Comment  Read more

회사를 여럿 바꾸면서 느낀 점

|

1. 아무 회사나 들어가지 말자, 하고 싶은 직무를 방향으로 가자(본인이 열정적인 것이 무엇인지 알자)

처음에는 취업이 힘들어서, 중견기업 대기업 회사 위주로 취업하기 쉬워보이는 직무로 지원을 하였다. 그때 Technical Support라는 직무를 맡게 되었고, 사실 별다른 기술을 배우는 것이 아닌, 몸으로 때워서 일이였다. 이에 회사에서 항상 무엇을 배우고, 외국어를 꾸준히 개발하기로 결심을 맺었다.

두번째 회사는 Midea Group이다. 사실 이쪽이 제일 하고 싶은 직무였다. 그러나 외국인으로써 일할 기회가 주어지지 않았고, 혹은 능력이 부족하여서 오퍼를 받지 못하였다. 또한 사실 돈이 적었다. 아무리 하고 싶은 직무라고 할지라도 어느정도 기본 돈이 필요하다고 생각했다.

세번째 회사는 PTC 기술영업이였다. 워라밸 최강, 연봉도 나쁘지 않았다. 다만 첫번째 조건과 마찬가지로 내 커리어가 멈추는 느낌이다. 기술영업보다 좀다 연구개발에 관심이 나한테 맞았다고 확신이 드는 순간이였고, 더 좋은 꾸준히 공부를 하고 경력을 쌓을 수 있는 연구개발로 계속 지원을 하였고, 결국 되었따.

2. 동료랑 친하게 지낼것

우리는 언젠가 회사에 나오게 된다. 결국 남는 건 회사 안에서 지지고 볶았던 동료들이다. 그들이 자산이며, 그들은 결국 나를 증명해주는 사람들이다. 또한 회사 안에서 당신을 위로해주고, 스트레스 주는 사람도 동료이다. 인간은 어쩔 수 없이 상처를 받고 치유를 받는다. 혼자 얼음 장벽을 치고, 동료들과 친해지지 않는다면, 언젠가 혼자 치료할 수 없을 많큼 많은 힘듬이 있고, 이는 직장 스트레스까지 쌓이게 될것이다.

3. 겸손, 그리고 광대가 될줄 아는 용기

특히 신입사원으로써 패기도 중요하다. 다만 그 패기가 건방짐으로 보이게 된다면 문제가 된다고 생각이 된다. 그렇기 때문에 유쾌한, 일을 잘 할 수 있다라는 패기를 보이는 것이 중요하며 그것의 기반은 겸손이여야 한다. 또한 사람과 사람이 친해지는데 있어, 자신의 단점을, 허물을 보여주는 것이 상대방과 친해지는데 많은 도움이 되고, 회사 안에서도 긍정적인 사람으로 임해질 수 있다.

4. 딴일 하지 말고 일에 집중할 것.

일에 100% 집중하는것이 중요하다. 그래야만, 원하는 목표를 이를 수 있다. 대충대충 하거나 딱 적당한 수준으로만 한다면, 언젠가 당신은 후배들에게 따라잡히게 될 것이고, 도태가 될것이다. 그러기 떄문에 주어진 시간에는 일에 집중을하고, 일을 사랑하여, 꼭 주어진 일 시간뿐만 아니더라도 개인의 시간을 쪼개서 자기 계발을 할 수 있는 능력이 중요하다.

5. 항상 감사한 마음을 가질것.

모든 순간 감사한 마음을 가져라. 좋은일이든 나쁜일이든. 상황을 나쁘게 볼것이 없다. 돌파구를 찾는것이 중요한 것이지. 또한 퇴사를 하거나 분쟁이 생겼을때, 불평 불만, 부정적인 얘기만 한다면, 결국 회사 안에서도 평판이 나빠지고, 이직을 할때에도 순탄하게 되지 않을 가능성이 높다. 아름다운 이별을 위해서라도, 인생은 어떻게 될지 모르기 때문에, 항상 감사하는 마음으로 소중하게 사는것이 중요하다고 생각한다.

6. 자리는 항상 깨끗이.

자리만 봐도 이 사람이 어떤 마음 가짐으로 일하고 있는지 알 수 있다. 항상 정리 정돈을 잘 해놓고 일하는 것이 중요하다. 지저분하다면, 주변 동료로부터 인상이 좋지 않을 것이다. 즉, 자기 자리의 정리도 항상 완벽하게 정리하자.

7. 욕먹는 것을 두려워 하지 말자.

어려운일이 주어질 것이고, 못하는 일이 주어질 것이다. 다만 상사와 동료들에게 실망을 주기 싫어서 혼자 끙끙앓다가, 프로젝트가 망하며 폭팔하는 일이 생기면 안된다. 본인이 부족한 것을 안다면, 밤을 세더라도, 공부를 하여서 많은 실험과 연구를 해본다. 그래도 잘 안된다면, 그때가서 “이런 이런 시도를 해봤고, 이런 이런 공부를 했는데도 잘 모르겠습니다. 혹시 어떻게 하면 되는지 조언을 드려도 될까요?”라는 식으로 여쭤보고 지도를 받고 일을 하는 것이 중요하다. 첫번쨰 문제에 꼬리 물어 2번 3번 문제를 해결하지 못한다면, 정말 큰 문제이므로 본인의 실력을 의심하고, 수단과 방법을 사용하지 않고 실력을 늘리려 노력해야 된다.

Comment  Read more

인턴을 할 때 자세

|

인턴을 하면서 항상 명심을 해야 하는 자세

  1. 같이 일하고 싶은 사람을 뽑는 과정이다.
    • 겸손함이 중요하다. 내 잘남보다, 배우는 자세를 갖는게 중요하다.
    • 배우고자 열정적인 자세를 보여줘라.
    • 일 뿐만 아니라, 사람들하고 어울려라.(먼저 다가가고, 먼저 웃고, 여유잇는 제스처 등등 동료들을 편하게 느끼도록 해줘라)
    • 효율적으롤 일(즉, 일처리를 빠르게 잘하는 방법을 생각해본다.)
    • 모르는 것은 창피하다 생각하지 말고, 정중하고, 깊게 물어본다.
    • 솔직하자. 무조건 솔직하자. 그들은 당신이 거짓말을 하는지 안하는지 알고 있다.
  2. 팀워크
    • 개인의 임무를 끝냈지만, 동료를 도와주지 못해 임무를 끝내지 못한다면, 결국 나도 프로젝트에 실패하게 된것이다. 그러니 동료를 중요시 생각하자
    • 적극적으로, 남이 하기 싫은 일을 내가 맡아서 하자.
    • 개인적인 행동보다, 단체적인 행동을 하자. 프로젝트를 한다는 것은 여러 인원이 한 팀이 되는 것이도, 그 이루어진 팀은 하나하나 조직 세포처럼 협업이 좋아야 한다.
  3. 간절함
    • 대부분 취업이 힘든거 안다. 그래서 최대한 뽑아주려고, 좋은 점수 주려고 노력을 한다. 그렇기 때문에 수능 준비와 시험날 처럼 인생에 한번 뿐인 기회라 생각을 하고 열심히 준비를 하고 임해야 한다.
    • 얼마나 팀에 잘 맞는 인원인지, 사실 그들과 호흡 손과 발이 맞아야 함으로, 나의 개성을 밀고 나가는 것 보다, 융합을 하고 타협을 하며, 그룹에 속하려는 노력이 필요하다.
  4. 결론

내가 맡은 임무에 대해 열정을 다하며, 팀 동료와 자존심 싸움을 하지 말고, 타협을 해가며, 팀에 어울릴 수 있는 팀워크 있는 동료가 중요하다. 또한, 항상 배우는 자세, 겸손한 자세로 일을 하다 보면, 더 많은 것을 배울 수 있고, 선배님들 동료들도 더 많은 것들을 알려 줄 수 있다. 나 또한 인턴에 어려움을 겪고 있는 동료를 본다면, 개인적인 이기심 보다, 적극적으로 도와주면서 사람을 얻고, 지식을 얻고, 리더쉽을 얻는 것이 중요하다.

Comment  Read more