SlideShare ist ein Scribd-Unternehmen logo
1 von 34
Downloaden Sie, um offline zu lesen
project #2



    말의 여행


             자료구조 01분반 D0조


                        조장
               20093526 정준용
                        조원
               20113318 정예린
               20113315 정민정
               20113311 장동규
순서




                           •조원별 업무분담
                                  •일정 계획
                                  •문제 파악
-infix expression을 postfix expression으로 바꾸는 방법
                  -스택(stack)과 큐(queue)의 개념
                             •알고리즘 계획
                                   •소스구현
                •문제점 파악 / 해결법 토의
                                   •최종소스
1)조원별 업무 분담

정준용           최종 보고서 작성 및 프로젝트 총괄

              과제(해밀턴의 순환, 기사의 여행)
장동규           자료 조사 및 시간·공간 복잡도 조
              사
              알고리즘(스택, 큐, 백트래킹)에 대
정민정           한 자료 조사 및 시간·공간 복잡도
              조사
              알고리즘에 대한 소스 구현 및 코딩
정예린
              작업
              알고리즘에 대한 소스 구현 및 코딩
이태구
              작업




2)일정계획
              과제에 대한 자료 조사 및 업무분담
03.27~03.29
              일정 계획
              스택, 큐, 백트래킹에 대한 이해 및
03.29~04.03
              알고리즘 구상
              구성된 알고리즘을 기반으로 초안소
04.03~04.05   스 구현 및 문제점 탐색과 해결에
              대한 토의

04.05~04.10   최종 소스 확인 및 최종보고서 작성
3)문제파악
말의 여행
목표
자료구조에서 다음과 같은 사항을
1. 스택과 큐의 개념을 이용하고 사용하는 법을 안다.
2. 백트래킹의 사용법을 안다.
3. 프로그램의 시간/공간 복잡도를 분석 할 수 있다.
구성 요소
장기판은 다음과 같이 가로 9줄, 세로 10줄로 구성되어 있다. 장기판은 다음
그림과 같이 좌표가 주어진다.




·말은 이동하고자 하는 방향으로 먼저 선을 따라 한 칸 이동하고 다음은 대
각선으로 한 칸 이동한다.
·말의 여행은 장기판의 특정 곳에서 출발하여 전 장기판을 오직 한번씩 모두
방문하는 것을 말한다.
과제
1. 장기판의 네 모서리 중 한 곳에서 시작하는 말의 이동 프로그램을 작성하
시오.
·입력 : 0,0(혹은 8,9 혹은 8,0 혹은 8,9)
·출력 : 이동한 좌표점을 모두 출력
2,1
3,3
.....
※과제에 대한 참고자료


◉해밀턴 경로(Hamilton Path)


     해밀턴 경로는 어떤 그래프에서 모든 꼭지점을 단 한번만 지나는 경
로를 의미한다. 해밀턴 경로가 존재하기 위한 조건은 그래프의 정점의 수가
n이라고 할 때, 정점 1개 또는 2개는 n/2 미만의 차수를 가져야 한다.
     또한, 해밀턴 회로, 해밀턴 사이클은 모든 꼭지점을 단 한번만 지나는
회로를 의미한다. 해밀턴 회로의 존재는 정점 차수와 관계가 없으며 모든 정
점의 차수가 짝수라 하더라도 존재하는 경우도 있고 그렇지 않은 경우도 있
다. 결과적으로 해밀턴 회로를 찾기 위한 조건은 아직 밝혀지지 않았으며 시
행착오에 의해 찾아야만 한다.




             ·정십이면체의 모든 꼭짓점을 지나는 해밀턴 회로
◉기사의 여행(Knight’s Tour)


     기사의 여행은 체스판에서 기사와 관련된 수학 문제이다. 기사는 빈
체스판 위에 올려져 있으며, 체스의 규칙에 따라 움직이는데, 정확히 한번만
각 구역을 방문해야만 한다. 만약 기사가 시작한 곳으로 다시 돌아온다면,
기사의 여행은 닫힌 여행이라 불리게 된다.(그렇게 하면 여행은 그 판 위에
서 같은 경로로 시작하게 된다.) 그렇지 않으면 그 여행은 열려 있는 것이
다.




                         ·기사 여행의 예




                 ·기사의 여행을 좌표에 적용한 예
4)알고리즘 계획

※알고리즘에 대한 참고 자료


                   스택(Stack)


스택이란 먼저 들어간 자료가 나중에 나오는 자료구조이다. 후입선출(Last
In First Out)의 형태를 띄고 있다. 간단하게 그림으로 표현하면 아래와 같
다.


1. 1번 자료부터 아래에서 위로 차례대로 쌓아 올라간다.




2. 가장 위에 있는 자료(3번, 가장 나중에 들어간 자료)부터 차례대로 꺼낸
다.




이러한 스택의 가장 윗부분을 나타내는 포인터를 TOP이라고 한다. 반대로
가장 아랫부분을 가리키는 포인터는 BOTTOM이라고 한다. 스택의 맨 위 자
료를 출력하는 것을 POP();이라고 하며 스택에 자료를 넣는 것은 PUSH();
라고 한다.




또한 아무것도 없는 스택에서 POP();로 데이터를 꺼내려는 경우 발생하는
에러를 Stack Underflow 라고 하며, 반대로 이미 꽉 찬 상태의 스택에
PUSH(); 로 데이터를 넣으려는 경우 발생하는 에러는 Stack Overflow라고
한다. 이러한 경우들에는 예외처리를 해주어야 한다.
                                   출처 : http://blog.nextcube.pe.kr



                        큐(Queue)


큐는 스택과는 달리 먼저 들어간 데이터를 가장 먼저 출력하는 선입선출
(First In First Out)형식의 자료구조이다.


1. 1번 자료부터 순서대로 넣는다.




2. 1번부터 순서대로 출력한다
큐의 맨 앞의 출구에서 대기 중인 데이터를 Front라고 한다. 반대로 큐의
맨 마지막에서 대기 중인 데이터를 Rear라고 한다.
큐의 맨 앞에서 대기 중인 자료를 출력하는 것을 Dequeue();라고 하며, 큐
에 자료를 넣는 것을 Enqueue();라고 한다.
또한 아무것도 없는 큐에 Depueue();로 데이터를 출력하려는 경우 Queue
Underflow라는 에러가 뜨며, 꽉 찬 큐에 Enpueue();로 데이터를 넣으려는
경우에도 Queue Overflow라는 에러가 뜬다.
이러한 큐는 크게 두 가지의 종류로 나눌 수 있다. 원형큐(순환큐), 링크드
큐가 바로 그것이다.


1.순환큐




Enqueue는 Rear에서만, Dequeue는 Front에서만 일어난다.


2.링크드 큐




링크드 큐는 위에서 예시로 들면서 설명한, 선형 구조의 큐이다.


                             출처 : http://lwove.egloos.com/2274841
백트래킹(Back Tracking)


백트래킹은 모든 조합을 시도해서 문제의 해를 찾는 방법이다. 백트래킹은
해를 얻을때까지 모든 경우의 수를 시도하기 때문에 언젠가는 반드시 그 답
을 찾아낸다. 백트래킹은 우선 모든 가능성을 나무처럼 구성할 수 있고, 나
무의 가지 중에 해결책이 이다.
백트래킹은 문제에서 요구하는 답을 무조건 내놓을 수 있다는 장점을 가지
고 있지만, 모든 경우의 수를 검사하기 때문에 시간이 오래 걸린다는 단점이
있다.
백트래킹에는 크게 두 가지 방법이 있는데, 우선 깊이 우선 탐색(Depth
First Search)이 있다. 깊이 우선 탐색이란 가장 처음에서 가장 아래쪽까지
들어갔다가 더 이상 들어갈 곳이 없으면 위로 나와서 다른 곳으로 들어가고,
또 길이 없으면 다시 나와 다른 곳으로 들어가는 과정을 되풀이하여 답을
찾아 나가는 알고리즘을 말한다. 이 알고리즘은 스택을 사용하여 수현 할 수
있는데, 스택이 후입선출의 형식을 가진 자료구조이기 때문에, 깊이 들어갔
다가 바로 위로 나오는 것을 스택의 top을 빼는 것으로 간단하게 구현할 수
있기 때문이다. 또한 백트래킹에는 너비우선탐색(Breadth First Search)이라
는 방법도 존재한다.
너비우선탐색은 처음의 경우를 모두 조사하고, 답이 없다면 그 다음 깊이
(다음 단계)의 경우의 수를 모두 조사하고, 거기에도 답이 없다면 그 다음으
로 넘어가는 식으로 우선 한 라인을 모두 탐색하고 답이 없다면 다음 라인
으로 넘어가는 방식이다. 이 방법은 큐를 이용하여 구현할 수 있다.
                   출처 : http://blog.naver.com/dimigozzang/110122521040


              Infix expression(중위 표기법)
중위표기법이란 우리가 가장 흔하게 쓰는 수식이다. 연산자가 피연산자와
피연산자 사이에 존재하는 수식으로 a+2 같은 형태의 수식이다.



              Postfix expression(후위 표기법)
후위표기법이란 연산자가 피연산자 뒤에 들어가는 수식이다. a 2 + 의 형
태의 수식이며, 중위표기법과 달리 괄호를 쓸 필요가 없으므로 연산의 효율
성이 높아진다.
Infix → Postfix
중위 표기법을 후위 표기법으로 바꾸기 위해서는 Stack을 이용한다.
기본적인 변환 알고리즘은 아래와 같다.


1. ‘(’를 만나면 무시하고 넘긴다.
2. 피 연산자를 만나면 그대로 출력한다
3. 연산자를 만나면 스택에 Push한다.
4. ‘)’를 만나면 스택에서 Pop하여 출력한다.


예를 들어 (a+b)*c+d*k 라는 수식을 위의 알고리즘을 참고하여 후위표기법
으로 변환한다고 하자. 우선 표시할 수 있는 모든 괄호를 표시하자. 그러면
저 수식을 ((a+b)*c)+(d*k) 로 나타낼 수 있다. a는 피연산자 이므로 그대
로 출력하고, 그 다음 나오는 +는 연산자이므로 스택에 푸시 한다. 다음에
나오는 b 역시 피연산자이므로 그대로 출력하며, 그리고 )가 나오므로 스택
에 저장되어있던 +를 꺼내온다.


이런 식으로 알고리즘을 따라가면 저 수식이 후위 표기법으로 a b + c * d
k * + 로 나타 낼 수 있다.


                      출처 : http://blog.naver.com/ryutuna/100122313091
                           http://blog.naver.com/checkdisk/110104634673
알고리즘 1

말의 여행 알고리즘
1. 처음 초기위치는 모두 0으로 초기화 시켜준다.
2. 처음 위치에서 이동하면서 갈림길을 발견하면 0은 갈 수 있는 길...ㄱ.
                                 1은 갈 수 없는 길...ㄴ.
ㄱ.갈 수 있는 길은 계속 진행한다.
ㄴ.갈 수 없는 길이므로 원래 자리로 돌아온다. → 백트래킹


3. 규칙을 기본으로 자리이동시의 좌표 값을 저장한다.→스택


※스택
LIFO : Last In First Out
같은 타입의 집합을 관리.
push : 자료를 집어넣는 행위.
pop : 자료를 빼 내는 행위.
push의 동작
-push로 데이터를 넣으며, push 함수에선 top을 1 증가시킴.
-top을 인자로 가지는 배열에 입력 data를 넣음.
-top과 할당된 스택의 크기를 비교하여 top이 스택의 마지막 요소보다 작을
때만 push.
-이 조건에 맞지 않으면 에러를 리턴.(오버플로우)
pop의 동작
-Top 위치의 값을 읽고 Top은 하나 감소.
-스택이 텅 비어서 더 꺼낼 데이터가 없을 때 -1이라는 에러 리턴.(언더플
로우)


4. 출력 시는 스택으로 저장한 입력 값은 큐로 출력.
알고리즘 2

일차원 배열을 이용한 말의여행 소스 구현 알고리즘


①말의 좌표를 십진수 화 시킨다.
②말이 해당하는 좌표에서 갈 수 있는 여덟 가지 경우를 계산한다.
③계산 한 값 중 장기판 내부에 있는 제일 작은 수의 경우를 스택배열에 저
장한다.
④제일 작은 수의 경우에 갈 수 있는 여덟 가지 경우를 다시 계산해준다.
⑤또 다시 나온 제일 작은 수의 경우를 스택에 저장해준다.
⑥만일 스택에 저장하는 과정에서 중복되는 경우가 있으면 다시 그 앞에 저
장된 값으로 돌아간다.→백트래킹
⑦돌아간 값은 앞에서 중복되었던 경우를 skip하고 다른 경우의 수를 저장한
다.


(0,0)을 입력 한다고 가정하면, 제일 작은 숫자들이 배열에 담기게 된다.


             .
             .
             .
             .
             .
             .
             .
             .
             .
             .
             .
             2,4 ←밑의 수들과 같은 방식으로 들어간 다른 값.
             1,2 ←계산된 제일 작은 십진수화 된 좌표 값.
             0,0 ←(0,0)부터 담기게 됨.
최종 알고리즘

1차 배열 또는 2차 배열을 사용해 장기판을 만든 뒤 말이 움직이는 좌표로
가는 배열을 생성하여 상황에 맞게 말을 움직인다.


2차 배열일 경우에는
①말의 좌표를 2차 배열로 표현한다.
②x와 y가 갈 수 있는 여덟 가지 경우를 입력한 배열의 값을 더해 말의 다
음 이동값을 계산한다.
③계산한 값을 스택에 넣는다.
④스택에 계산한 값이 있을 때 Pop한다.
⑤Pop을 한 경우에는 다른 값을 스택에 넣는다.



1차 배열일 경우에는
①말의 좌표를 십진수 화 시킨다.
②말이 해당하는 좌표에서 갈 수 있는 여덟 가지 경우를 계산한다.
③계산 한 값 중 장기판 내부에 있는 제일 작은 수의 경우를 스택배열에 저
장한다.
④제일 작은 수의 경우에 갈 수 있는 여덟 가지 경우를 다시 계산해준다.
⑤또 다시 나온 제일 작은 수의 경우를 스택에 저장해준다.
⑥만일 스택에 저장하는 과정에서 중복되는 경우가 있으면 다시 그 앞에 저
장된 값으로 돌아간다.→백트래킹
⑦돌아간 값은 앞에서 중복되었던 경우를 skip하고 다른 경우의 수를 저장한
다.


(0,0)을 입력 한다고       가정하면, 제일 작은 숫자들이 배열에 담기게 된
다.              .
                .
                .
                .
                .
                .
                .
.
                         .
                         .
                         .
                         2,4
                         1,2
                         0,0 ←밑의 수들과 같은 방식으로 들어간 다른 값.

                        ←계산된 제일 작은 십진수화 된 좌표 값.
                        ←(0,0)부터 담기게 됨.


5)소스 구현
알고리즘 1에 대한 소스
#include <stdio.h>
#define X 9
#define Y 8
#define MOVE 8


int board[X][Y];
int stack[180];
int mvx[MOVE] = {-2, -1, 1, 2, 2, 1, -1, -2};
int mvy[MOVE] = {1, 2, 2, 1, -1, -2, -2, -1};


int push(int i, int move);
int pop(int i);
int check(int a, int x, int y);


int main(void)
{
       int a=0, x, y, i, j=0;
       reset:
       scanf("%d %d", &x, &y);


       for(i=0; i<180; i++)
                  stack[i]=-1;
if(x < 0 || x > X || y < 0 || y > Y)
{
      printf("다시 입력하시오");
      goto reset;
}
for(i=0; i<180;)
{
      push(i, x);
      push(i+1,y);
      for(;j<MOVE;)
      {
              up:
              x+=mvx[j];
              y+=mvy[j];
              if(x<0 || x>X || y<0 || y>Y)
              {
                        x-=mvx[j];
                        y-=mvy[j];
                        j=(j+1)%8;
                        goto up;
              }
              j=(j+1)%8;
              break;
      }
      if(check(a, x, y)==1)
      {
              pop(i);
      }
      i+=2;
}



for(i=0; i<180;)
{
                 printf("(%d,%d)", stack[i], stack[i+1]);
                 i+=2;
       }
       return 0;
}
int push(int i, int move)
{
       stack[i]=move;
}
int pop(int i)
{
       return i-=2;
}
int check(int a, int x, int y)
{
       for(a=0; a<180;)
       {
                 if(stack[a]==x && stack[a+1]==y)
                 {
                         return 1;
                         break;
                 }
                 a+=2;
       }
}

알고리즘 2에 대한 소스
#include<stdio.h>
int main()
{
       int stack[90];
       int x1[2]={-10,10},x2[2]={-20,20};
       int y1[2]={-2,2},y2[2]={-1,1};
int a,b,i=0,j,out,x,y;


scanf("%d %d",&x,&y);
a=x,b=y;


//for(
for(i=0;i<90;)
{
         //말이 갈 수 있는 8가지 모든 경우의 수
         a=x1[0]+a;
         b=y1[0]+b;


         if(b>=10 || a<=0 || b<=0)
         {
                a=a-x1[0];
                b=b-y1[0];


         }
         else
         {


                stack[i]=a+b;
                i++;
                a=x,b=y;
         }
         a=x1[0]+a;
         b=y1[1]+b;
         if(b>=10 || a<=0 || b<=0)
         {
                a=a-x1[0];
                b=b-y1[1];
         }
         else
{
       stack[i]=a+b;
       i++;
       a=x,b=y;
}
a=x1[1]+a;
b=y1[0]+b;
if(b>=10 || a<=0 || b<=0)
{
       a=a-x1[1];
       b=b-y1[0];
}
else
{
       stack[i]=a+b;
       i++;
       a=x,b=y;
}
a=x1[1]+a;
b=y1[1]+b;
if(b>=10 || a<=0 || b<=0)
{
       a=a-x1[1];
       b=b-y1[1];
}
else
{
       stack[i]=a+b;
       i++;
       a=x,b=y;
}


a=x2[0]+a;
b=y2[0]+b;
if(b>=10 || a<=0 || b<=0)
{
       a=a-x2[0];
       b=b-y2[0];
}
else
{
       stack[i]=a+b;
       i++;
       a=x,b=y;
}
a=x2[0]+a;
b=y2[1]+b;
if(b>=10 || a<=0 || b<=0)
{
       a=a-x2[0];
       b=b-y2[1];
}
else
{
       stack[i]=a+b;
       i++;
       a=x,b=y;
}
a=x2[1]+a;
b=y2[0]+b;
if(b>=10 || a<=0 || b<=0)
{
       a=a-x2[1];
       b=b-y1[0];
}
else
{
       stack[i]=a+b;
i++;
                 a=x,b=y;
          }
          a=x2[1]+a;
          b=y2[1]+b;
          if(b>=10 || a<=0 || b<=0)
          {
                 a=a-x2[1];
                 b=b-y2[1];
          }
          else
          {
                 stack[i]=a+b;
                 i++;
                 a=x,b=y;
          }
          /*for(j=0;j<i;j++)
          {
                 printf("i=%d stack=%dn",i,stack[j]);
          }*/


          a=(int)stack[0]/10; //경우의 수 중에 스택의 맨 위 쪽에 저
장 된 부분을 각각 x,y 좌표에 저장함.
          b=stack[0]%10;
          x=a,y=b;
          printf("a=%d b=%dn",a,b);
          for(j=0;j<=i;j++)
          {
                 stack[j]=stack[j+1];
          }


    }
    /*for(j=0;j<i-1;j++)
    {
printf("%dn",stack[j]);
      }*/


      //i=0;
      /*while(1)
      {
               if(i>90)
               {
                       break;
               }
               else
               {
                       printf("%dn",stack[i]);
                       i++;
               }
      }*/
/*}
for(j=0;j<i;j++)
               {
                       printf("i=%d stack=%dn",i,stack[j]);
               }*/


}


1)문제점 : 갱신은 성공 하였으나, 첫 번째 여행을 끝마친 후 그 뒤의 여행
에서 자료 갱신이 안 되며 이미 지나간 길인지 검사가 되지 않음.
#include<stdio.h>
int main()
{
      int stack[90];
      int x1[2]={-10,10},x2[2]={-20,20};
      int y1[2]={-2,2},y2[2]={-1,1};


      int a,b,i=1,j=0,o,x,y;
scanf("%d %d",&x,&y);
   a=x,b=y;
   stack[0]=a+b;



   up:
   while(1)
   {
         a=x,b=y;
         //말이 갈 수 있는 8가지 모든 경우의 수
         a=-10+a;
         b=-2+b;


         if(b>=10 || a<=0 || b<=0 || a<10)
         {
                a=a-(-10);
                b=b-(-2);
         }
         else
         {
                stack[i]=a+b;


                break; //각 경우의 수의 경우 스택에 저장이 되면 바
로 포문을 빠져 나오도록 설계⟶가장 작은 수를 스택에 저장하고 더 이상
검색하지 않음.
         }
         a=-10+a;
         b=2+b;
         if(b>=10 || a<10 || a<=0 || b<=0)
         {
                a=a-(-10);
                b=b-2;
         }
else
{
       stack[i]=a+b;


       break;
}
a=10+a;
b=-2+b;
if(b>=10 || a<10 || a<=0 || b<=0)
{
       a=a-10;
       b=b-(-2);
}
else
{
       stack[i]=a+b;


       break;
}
a=10+a;
b=2+b;
if(b>=10 || a<10 || a<=0 || b<=0)
{
       a=a-10;
       b=b-2;
}
else
{
       stack[i]=a+b;


       break;
}


a=-20+a;
b=-1+b;
if(b>=10 || a<10 || a<=0 || b<=0)
{
       a=a-(-20);
       b=b-(-1);
}
else
{
       stack[i]=a+b;


       break;
}
a=-20+a;
b=1+b;
if(b>=10 || a<10 || a<=0 || b<=0)
{
       a=a-(-20);
       b=b-1;
}
else
{
       stack[i]=a+b;


       break;
}
a=20+a;
b=-1+b;
if(b>=10 || a<10 || a<=0 || b<=0)
{
       a=a-20;
       b=b-(-1);
}
else
{
stack[i]=a+b;


                    break;
             }
             a=20+a;
             b=1+b;
             if(b>=10 || a<10 || a<=0 || b<=0)
             {
                    a=a-20;
                    b=b-1;
             }
             else
             {
                    stack[i]=a+b;


                    break;
             }
      }


      printf("i=%d",i);
             /*for(o=0;o<i-1;o++)
             {
                             if(stack[o]!=stack[i-1])
                             {


x=(int)stack[i-1]/10,y=stack[i-1]%10;
                                   j=2;
                                   printf("stack=%d",stack[i-1]);
                                   goto up; // 가장 작은 수를 저장 한 후
그 수가 스택에 원래 존재하는지 안하는지를 판별 후 존재하지 않으면 x,y
좌표에 가장 마지막에 저장된 스택을 저장하고 다시 포문 함수를 불러냄.
                                   break;
                             }
                             else if(stack[o]==stack[i-1])
{
                           j=1;
                           stack[i-1]='0';
                    }
             /*else if(stack[i-1]==stack[o])
             {
                     break;
             }*/


    //}


    for(o=0;o<i;o++)
    {
             printf("stack=%dn",stack[o]);
    }
    /*printf("%dn",j);
    printf("x=%d y=%d",x,y);
    **?/


    /*a=(int)stack[1]/10;
    b=stack[1]%10;
    x=a,y=b;
    printf("a=%d b=%dn",a,b);
    for(j=0;j<=i;j++)
    {
             stack[j]=stack[j+1];
    }
    i=i-1;
    for(j=0;j<i;j++)
    {
             printf("%dn",stack[j]);
    }*/


}
최종소스
#include <stdio.h>


// c+2=x번¹ø째A°의AC 좌AA표C¥
// ex) c=15면¸e 17번¹ø째A°의AC 좌AA표C¥
int main()


{
int a,b,c;
scanf("%d %d",&a,&b);
printf("1번¹ø째A° : %d,%dn",a,b);
if(a==0&&b==0)
{
for(c=0; c<63; c++)
{
if(a<2&&b<8)
{
if(a%2==0||c==29)
{
a=a+1;
b=b+2;
printf("%d번¹ø째A° : %d,%dn",c+2,a,b);
}
// c=29는´A 원¿ø래·¡ 아¾Æ래·¡의AC 조A¶건°C(else)을A≫ 만¸¸족A·하CI지Ao만¸¸ 그±×렇·¸게°O 된μ
E다´U면¸e 0,2로·I 중Aß복º¹이AI 되μC기±a 때¶§문¹�에¿¡ 다´U른¸¥ 방¹æ향Ca으A¸로·I 가°¡야¾ß 함
CO
else if(c==44||c==62)
{
a=a+2;
b=b+1;
printf("%d번¹ø째A° : %d,%dn",c+2,a,b);
}
// c=44도μμ 물¹°론·Ð 아¾Æ래·¡의AC 조A¶건°C(else)을A≫ 만¸¸족A·하CI지Ao만¸¸ 그±×러·?면¸e 0,3
으A¸로·I 중Aß복º¹이AI 되μC기±a 때¶§문¹�에¿¡ 다´U른¸¥ 방¹æ향Ca으A¸로·I 가°¡야¾ß 함CO
// c=62도μμ 물¹°론·Ð 아¾Æ래·¡의AC 조A¶건°C(else)을A≫ 만¸¸족A·하CI지Ao만¸¸ 그±×러·?면¸e 0,5
으A¸로·I 중Aß복º¹이AI 되μC기±a 때¶§문¹�에¿¡ 다´U른¸¥ 방¹æ향Ca으A¸로·I 가°¡야¾ß 함CO
else
{
a=a-1;
b=b+2;
printf("%d번¹ø째A° : %d,%dn",c+2,a,b);
}
}
else if(a<7&&b>7)
{
if(b%2==0)
{
a=a+2;
b=b+1;
printf("%d번¹ø째A° : %d,%dn",c+2,a,b);
}
else
{
a=a+2;
b=b-1;
printf("%d번¹ø째A° : %d,%dn",c+2,a,b);
}
}
else if(a>6&&b>1)
{
if(a%2==0)
{
a=a-1;
b=b-2;
printf("%d번¹ø째A° : %d,%dn",c+2,a,b);
}
else
{
a=a+1;
b=b-2;
printf("%d번¹ø째A° : %d,%dn",c+2,a,b);
}
}
else if((a>1&&b<2)||c==30||c==46)
{
if(b%2==0)
{
a=a-2;
b=b+1;
printf("%d번¹ø째A° : %d,%dn",c+2,a,b);
}
else if(c==15||c==30||c==46)
{
a=a-2;
b=b+1;
printf("%d번¹ø째A° : %d,%dn",c+2,a,b);
}
// 17번¹ø째A°가°¡ 되μC는´A c=15에¿¡서¼­ 일AI반¹Y적Au으A¸로·I 간°£다´U면¸e 0,0이AI 되μC서¼­
중Aß복º¹이AI되μC기±a 때¶§문¹�에¿¡ 다´U른¸¥ 방¹æ향Ca으A¸로·I 가°¡야¾ß 함CO
// 32번¹ø째A°가°¡ 되μC는´A c=30에¿¡서¼­ 일AI반¹Y적Au으A¸로·I 간°£다´U면¸e 1,5이AI 되μC서¼­
중Aß복º¹이AI되μC기±a 때¶§문¹�에¿¡ 다´U른¸¥ 방¹æ향Ca으A¸로·I 가°¡야¾ß 함CO
// 48번¹ø재Ac가°¡ 되μC는´A c=46에¿¡서¼­도μμ 마¸¶찬Au가°¡지Ao로·I 일AI반¹Y적Au으A¸로·I 간°
£다´U면¸e 1,6이AI 되μC서¼­ 중Aß복º¹이AI되μC기±a 때¶§문¹�에¿¡ 다´U른¸¥ 방¹æ향Ca으A¸로·I
가°¡야¾ß 함CO
else
{
a=a-2;
b=b-1;
printf("%d번¹ø째A° : %d,%dn",c+2,a,b);
}
}
else
{
a=a-1;
b=b+2;
printf("%d번¹ø째A° : %d,%dn",c+2,a,b);
}
// c=44에¿¡ 의AC하CI여¿ⓒ c=45는´A 위A§의AC 조A¶건°C이AI 하CI나³ª도μμ 성¼º립¸³하CI지Ao않
¾E는´A 새≫o로·I운¿i 좌AA표C¥가°¡ 나³ª왔¿O기±a 때¶§문¹�에¿¡ 나³ª머¸O지Ao 경°æ우¿i에¿¡ 속¼O
한CN다´U.
}
// c=62 즉Ai 65번¹ø째A° 좌AA표C¥까±i지Ao의AC 움¿o직A÷임AO
for(c=63; c<89; c++)
{
// c=63 즉Ai 65번¹ø째A° 좌AA표C¥부ºI터AI 시½A작AU
if(a<4&&b<6)
{
if(a%2==0)
{
a=a+1;
b=b+2;
printf("%d번¹ø째A° : %d,%dn",c+2,a,b);
}
else
{
a=a-1;
b=b+2;
printf("%d번¹ø째A° : %d,%dn",c+2,a,b);
}
}
else if(a<5&&b>5||c==69)
{
if(b%2==0||c==69)
{
a=a+2;
b=b+1;
printf("%d번¹ø째A° : %d,%dn",c+2,a,b);
}
// c=69에¿¡서¼­도μμ 정A¤상≫o적Au인AI 경°æ로·I로·I 움¿o직A÷인AI다´U면¸e 2,2가°¡ 되μC어¾i 중
Aß복º¹된μE 좌AA표C¥가°¡ 생≫y기±a므¹C로·I 다´U른¸¥방¹æ향Ca으A¸로·I 움¿o직A÷여¿ⓒ야¾ß 함
CO
else
{
a=a+2;
b=b-1;
printf("%d번¹ø째A° : %d,%dn",c+2,a,b);
}
}
else if(a>4&&b>3)
{
if(a%2==0)
{
a=a-1;
b=b-2;
printf("%d번¹ø째A° : %d,%dn",c+2,a,b);
}
else if(c==75)
{
a=a-1;
b=b-2;
printf("%d번¹ø째A° : %d,%dn",c+2,a,b);
}
// c=75는´A 원¿ø래·¡ 위A§의AC 조A¶건°C을A≫ 만¸¸족A·하CI지Ao만¸¸ 그±×러·?면¸e 6,4의AC 중
Aß복º¹된μE 좌AA표C¥가°¡ 생≫y기±a므¹C로·I 다´U른¸¥방¹æ향Ca으A¸로·I 이AI동μ¿한CN다´U.
else if(c==84)
{
a=a-2;
b=b+1;
printf("%d번¹ø째A° : %d,%dn",c+2,a,b);
}
// c=84는´A 아¾Æ래·¡의AC 조A¶건°C을A≫ 만¸¸족A·하CI지Ao만¸¸ 그±×렇·¸게°O 된μE다´U면¸e 6,3
의AC 중Aß복º¹된μE 좌AA표C¥가°¡ 생≫y기±a므¹C로·I 다´U른¸¥방¹æ향Ca으A¸로·I 이AI동μ¿한CN다
´U.
else
{
a=a+1;
b=b-2;
printf("%d번¹ø째A° : %d,%dn",c+2,a,b);
}
}
else if(a>3&&b<4)
{
if(b%2==0)
{
a=a-2;
b=b+1;
printf("%d번¹ø째A° : %d,%dn",c+1,a,b);
}
else if(c==88)
//마¸¶지Ao막¸· 좌AA표C¥
{
a=a-1;
b=b+2;
printf("%d번¹ø째A° : %d,%dn",c+2,a,b);
}
// c=88에¿¡서¼­는´A 움¿o직A÷일AI 곳°÷이AI 한CN곳°÷ 밖¹U에¿¡ 없¾ø기±a 때¶§문¹�에¿¡ 마¸¶지
Ao막¸· 좌AA표C¥로·I 이AI동μ¿한CN다´U.
else
{
a=a-2;
b=b-1;
printf("%d번¹ø째A° : %d,%dn",c+1,a,b);
}
}
else if(c==76)
{
a=a+2;
b=b-1;
printf("%d번¹ø째A° : %d,%dn",c+1,a,b);
}
// c=76은Aº 위A§의AC 조A¶건°C을A≫ 만¸¸족A·하CI는´A 곳°÷이AI 없¾ø기±a 때¶§문¹�에¿¡ 중Aß
복º¹된μE 좌AA표C¥를¸| 피CC하CI여¿ⓒ 다´U른¸¥ 곳°÷으A¸로·I 이AI동μ¿한CN다´U.
}
}
return 0;
}
코딩결과
알고리즘 1




알고리즘 2
6)문제점 파악/해결법 토의
현재 모든 소스에서 백트래킹이 실행되지 않고 있다. 길을 가다 막혔을 때
다른 방향으로 갈 수 있는 곳까지 백트래킹을 해야 하지만 한번 밖에 되지
않아 같은 값만 계속 출력하게 된다. 이 문제를 해결하기 위해 백트래킹과
스택에 대한 자료를 계속 찾아보고 다양한 방면으로 시도를 해보았으나 해
결되지는 않았다.
마지막 최종 소스에서는 이전과는 다른 방법으로 진행해보려 했으나 역시
백트래킹이 실행되지 않았다.

Weitere ähnliche Inhalte

Was ist angesagt?

이산치3보고서
이산치3보고서이산치3보고서
이산치3보고서
KimChangHoen
 
Javascript개발자의 눈으로 python 들여다보기
Javascript개발자의 눈으로 python 들여다보기Javascript개발자의 눈으로 python 들여다보기
Javascript개발자의 눈으로 python 들여다보기
지수 윤
 
1.자료구조와 알고리즘(강의자료)
1.자료구조와 알고리즘(강의자료)1.자료구조와 알고리즘(강의자료)
1.자료구조와 알고리즘(강의자료)
fmbvbfhs
 

Was ist angesagt? (20)

이산치3보고서
이산치3보고서이산치3보고서
이산치3보고서
 
HI-ARC PS 101
HI-ARC PS 101HI-ARC PS 101
HI-ARC PS 101
 
Javascript개발자의 눈으로 python 들여다보기
Javascript개발자의 눈으로 python 들여다보기Javascript개발자의 눈으로 python 들여다보기
Javascript개발자의 눈으로 python 들여다보기
 
R 기본-데이타형 소개
R 기본-데이타형 소개R 기본-데이타형 소개
R 기본-데이타형 소개
 
Binary Search
Binary SearchBinary Search
Binary Search
 
Effective Modern C++ MVA item 18 Use std::unique_ptr for exclusive-ownership ...
Effective Modern C++ MVA item 18 Use std::unique_ptr for exclusive-ownership ...Effective Modern C++ MVA item 18 Use std::unique_ptr for exclusive-ownership ...
Effective Modern C++ MVA item 18 Use std::unique_ptr for exclusive-ownership ...
 
Haskell study 14
Haskell study 14Haskell study 14
Haskell study 14
 
1.자료구조와 알고리즘(강의자료)
1.자료구조와 알고리즘(강의자료)1.자료구조와 알고리즘(강의자료)
1.자료구조와 알고리즘(강의자료)
 
Haskell study 10
Haskell study 10Haskell study 10
Haskell study 10
 
2012 Ds 01
2012 Ds 012012 Ds 01
2012 Ds 01
 
Haskell study 9
Haskell study 9Haskell study 9
Haskell study 9
 
2012 Ds 06
2012 Ds 062012 Ds 06
2012 Ds 06
 
자료구조05
자료구조05자료구조05
자료구조05
 
자료구조05
자료구조05자료구조05
자료구조05
 
Data Structures
Data StructuresData Structures
Data Structures
 
Haskell study 13
Haskell study 13Haskell study 13
Haskell study 13
 
강의자료5
강의자료5강의자료5
강의자료5
 
[C++ Korea] Effective Modern C++ MVA item 8 Prefer nullptr to 0 and null +윤석준
[C++ Korea] Effective Modern C++ MVA item 8 Prefer nullptr to 0 and null +윤석준[C++ Korea] Effective Modern C++ MVA item 8 Prefer nullptr to 0 and null +윤석준
[C++ Korea] Effective Modern C++ MVA item 8 Prefer nullptr to 0 and null +윤석준
 
Startup JavaScript 4 - 객체
Startup JavaScript 4 - 객체Startup JavaScript 4 - 객체
Startup JavaScript 4 - 객체
 
HI-ARC PS 102 Brute Force
HI-ARC PS 102 Brute ForceHI-ARC PS 102 Brute Force
HI-ARC PS 102 Brute Force
 

Andere mochten auch (17)

자료구조06
자료구조06자료구조06
자료구조06
 
Radios
RadiosRadios
Radios
 
자료구조01
자료구조01자료구조01
자료구조01
 
Análisis de radios
Análisis de radiosAnálisis de radios
Análisis de radios
 
자료구조01
자료구조01자료구조01
자료구조01
 
이산수학07
이산수학07이산수학07
이산수학07
 
Análisis de radios de Janeth Crespo
Análisis de radios  de Janeth CrespoAnálisis de radios  de Janeth Crespo
Análisis de radios de Janeth Crespo
 
이산수학05
이산수학05이산수학05
이산수학05
 
이산수학02
이산수학02이산수학02
이산수학02
 
Wood
WoodWood
Wood
 
이산수학04
이산수학04이산수학04
이산수학04
 
이산수학03
이산수학03이산수학03
이산수학03
 
자료구조03
자료구조03자료구조03
자료구조03
 
이산수학06
이산수학06이산수학06
이산수학06
 
Heart disease
Heart diseaseHeart disease
Heart disease
 
A flowering tree
A flowering treeA flowering tree
A flowering tree
 
Artsofte_Компетенции для авиаперевозчиков
Artsofte_Компетенции для авиаперевозчиковArtsofte_Компетенции для авиаперевозчиков
Artsofte_Компетенции для авиаперевозчиков
 

Ähnlich wie 자료구조02

Project#2말의여행 Hwp
Project#2말의여행 HwpProject#2말의여행 Hwp
Project#2말의여행 Hwp
Kimjeongmoo
 
자료구조5보고서
자료구조5보고서자료구조5보고서
자료구조5보고서
KimChangHoen
 
자료구조 02 최종 보고서
자료구조 02 최종 보고서자료구조 02 최종 보고서
자료구조 02 최종 보고서
pkok15
 
Project#5 최단거리 찾기 D0 Hwp
Project#5 최단거리 찾기 D0 HwpProject#5 최단거리 찾기 D0 Hwp
Project#5 최단거리 찾기 D0 Hwp
Kimjeongmoo
 
2012 Ds B2 02 Pdf
2012 Ds B2 02 Pdf2012 Ds B2 02 Pdf
2012 Ds B2 02 Pdf
kd19h
 
2012 Ds B2 02
2012 Ds B2 022012 Ds B2 02
2012 Ds B2 02
chl132435
 
자료구조 Project2
자료구조 Project2자료구조 Project2
자료구조 Project2
KoChungWook
 
2012 Ds A1 05
2012 Ds A1 052012 Ds A1 05
2012 Ds A1 05
seonhyung
 
자료구조 Project6
자료구조 Project6자료구조 Project6
자료구조 Project6
KoChungWook
 
2012 Dm A0 07 Pdf
2012 Dm A0 07 Pdf2012 Dm A0 07 Pdf
2012 Dm A0 07 Pdf
kd19h
 
2012 Dm A0 07 Pdf
2012 Dm A0 07 Pdf2012 Dm A0 07 Pdf
2012 Dm A0 07 Pdf
jinwookhong
 
이산치 과제7
이산치 과제7이산치 과제7
이산치 과제7
mil23
 

Ähnlich wie 자료구조02 (20)

사칙연산 프로그램
사칙연산 프로그램사칙연산 프로그램
사칙연산 프로그램
 
Project#2말의여행 Hwp
Project#2말의여행 HwpProject#2말의여행 Hwp
Project#2말의여행 Hwp
 
자료구조5보고서
자료구조5보고서자료구조5보고서
자료구조5보고서
 
자료구조 02 최종 보고서
자료구조 02 최종 보고서자료구조 02 최종 보고서
자료구조 02 최종 보고서
 
Project#5 최단거리 찾기 D0 Hwp
Project#5 최단거리 찾기 D0 HwpProject#5 최단거리 찾기 D0 Hwp
Project#5 최단거리 찾기 D0 Hwp
 
자구2번
자구2번자구2번
자구2번
 
2012 Ds B2 02 Pdf
2012 Ds B2 02 Pdf2012 Ds B2 02 Pdf
2012 Ds B2 02 Pdf
 
2012 Ds B2 02
2012 Ds B2 022012 Ds B2 02
2012 Ds B2 02
 
자료구조 Project2
자료구조 Project2자료구조 Project2
자료구조 Project2
 
자료구조 프로젝트
자료구조 프로젝트자료구조 프로젝트
자료구조 프로젝트
 
2012 Ds A1 05
2012 Ds A1 052012 Ds A1 05
2012 Ds A1 05
 
Equation Solving
Equation SolvingEquation Solving
Equation Solving
 
자료구조 Project6
자료구조 Project6자료구조 Project6
자료구조 Project6
 
파이썬 스터디 2주차
파이썬 스터디 2주차파이썬 스터디 2주차
파이썬 스터디 2주차
 
파이썬 데이터과학 레벨2 - 데이터 시각화와 실전 데이터분석, 그리고 머신러닝 입문 (2020년 이태영)
파이썬 데이터과학 레벨2 - 데이터 시각화와 실전 데이터분석, 그리고 머신러닝 입문 (2020년 이태영)파이썬 데이터과학 레벨2 - 데이터 시각화와 실전 데이터분석, 그리고 머신러닝 입문 (2020년 이태영)
파이썬 데이터과학 레벨2 - 데이터 시각화와 실전 데이터분석, 그리고 머신러닝 입문 (2020년 이태영)
 
2012 Dm A0 07 Pdf
2012 Dm A0 07 Pdf2012 Dm A0 07 Pdf
2012 Dm A0 07 Pdf
 
2012 Dm A0 07 Pdf
2012 Dm A0 07 Pdf2012 Dm A0 07 Pdf
2012 Dm A0 07 Pdf
 
이산치 과제7
이산치 과제7이산치 과제7
이산치 과제7
 
Python3 brief summary
Python3 brief summaryPython3 brief summary
Python3 brief summary
 
GopherCon Korea 2015 - Python 개발자를 위한 Go (이경찬)
GopherCon Korea 2015 - Python 개발자를 위한 Go (이경찬)GopherCon Korea 2015 - Python 개발자를 위한 Go (이경찬)
GopherCon Korea 2015 - Python 개발자를 위한 Go (이경찬)
 

자료구조02

  • 1. project #2 말의 여행 자료구조 01분반 D0조 조장 20093526 정준용 조원 20113318 정예린 20113315 정민정 20113311 장동규
  • 2. 순서 •조원별 업무분담 •일정 계획 •문제 파악 -infix expression을 postfix expression으로 바꾸는 방법 -스택(stack)과 큐(queue)의 개념 •알고리즘 계획 •소스구현 •문제점 파악 / 해결법 토의 •최종소스
  • 3. 1)조원별 업무 분담 정준용 최종 보고서 작성 및 프로젝트 총괄 과제(해밀턴의 순환, 기사의 여행) 장동규 자료 조사 및 시간·공간 복잡도 조 사 알고리즘(스택, 큐, 백트래킹)에 대 정민정 한 자료 조사 및 시간·공간 복잡도 조사 알고리즘에 대한 소스 구현 및 코딩 정예린 작업 알고리즘에 대한 소스 구현 및 코딩 이태구 작업 2)일정계획 과제에 대한 자료 조사 및 업무분담 03.27~03.29 일정 계획 스택, 큐, 백트래킹에 대한 이해 및 03.29~04.03 알고리즘 구상 구성된 알고리즘을 기반으로 초안소 04.03~04.05 스 구현 및 문제점 탐색과 해결에 대한 토의 04.05~04.10 최종 소스 확인 및 최종보고서 작성
  • 4. 3)문제파악 말의 여행 목표 자료구조에서 다음과 같은 사항을 1. 스택과 큐의 개념을 이용하고 사용하는 법을 안다. 2. 백트래킹의 사용법을 안다. 3. 프로그램의 시간/공간 복잡도를 분석 할 수 있다. 구성 요소 장기판은 다음과 같이 가로 9줄, 세로 10줄로 구성되어 있다. 장기판은 다음 그림과 같이 좌표가 주어진다. ·말은 이동하고자 하는 방향으로 먼저 선을 따라 한 칸 이동하고 다음은 대 각선으로 한 칸 이동한다. ·말의 여행은 장기판의 특정 곳에서 출발하여 전 장기판을 오직 한번씩 모두 방문하는 것을 말한다. 과제 1. 장기판의 네 모서리 중 한 곳에서 시작하는 말의 이동 프로그램을 작성하 시오. ·입력 : 0,0(혹은 8,9 혹은 8,0 혹은 8,9) ·출력 : 이동한 좌표점을 모두 출력 2,1 3,3 .....
  • 5. ※과제에 대한 참고자료 ◉해밀턴 경로(Hamilton Path) 해밀턴 경로는 어떤 그래프에서 모든 꼭지점을 단 한번만 지나는 경 로를 의미한다. 해밀턴 경로가 존재하기 위한 조건은 그래프의 정점의 수가 n이라고 할 때, 정점 1개 또는 2개는 n/2 미만의 차수를 가져야 한다. 또한, 해밀턴 회로, 해밀턴 사이클은 모든 꼭지점을 단 한번만 지나는 회로를 의미한다. 해밀턴 회로의 존재는 정점 차수와 관계가 없으며 모든 정 점의 차수가 짝수라 하더라도 존재하는 경우도 있고 그렇지 않은 경우도 있 다. 결과적으로 해밀턴 회로를 찾기 위한 조건은 아직 밝혀지지 않았으며 시 행착오에 의해 찾아야만 한다. ·정십이면체의 모든 꼭짓점을 지나는 해밀턴 회로
  • 6. ◉기사의 여행(Knight’s Tour) 기사의 여행은 체스판에서 기사와 관련된 수학 문제이다. 기사는 빈 체스판 위에 올려져 있으며, 체스의 규칙에 따라 움직이는데, 정확히 한번만 각 구역을 방문해야만 한다. 만약 기사가 시작한 곳으로 다시 돌아온다면, 기사의 여행은 닫힌 여행이라 불리게 된다.(그렇게 하면 여행은 그 판 위에 서 같은 경로로 시작하게 된다.) 그렇지 않으면 그 여행은 열려 있는 것이 다. ·기사 여행의 예 ·기사의 여행을 좌표에 적용한 예
  • 7. 4)알고리즘 계획 ※알고리즘에 대한 참고 자료 스택(Stack) 스택이란 먼저 들어간 자료가 나중에 나오는 자료구조이다. 후입선출(Last In First Out)의 형태를 띄고 있다. 간단하게 그림으로 표현하면 아래와 같 다. 1. 1번 자료부터 아래에서 위로 차례대로 쌓아 올라간다. 2. 가장 위에 있는 자료(3번, 가장 나중에 들어간 자료)부터 차례대로 꺼낸 다. 이러한 스택의 가장 윗부분을 나타내는 포인터를 TOP이라고 한다. 반대로
  • 8. 가장 아랫부분을 가리키는 포인터는 BOTTOM이라고 한다. 스택의 맨 위 자 료를 출력하는 것을 POP();이라고 하며 스택에 자료를 넣는 것은 PUSH(); 라고 한다. 또한 아무것도 없는 스택에서 POP();로 데이터를 꺼내려는 경우 발생하는 에러를 Stack Underflow 라고 하며, 반대로 이미 꽉 찬 상태의 스택에 PUSH(); 로 데이터를 넣으려는 경우 발생하는 에러는 Stack Overflow라고 한다. 이러한 경우들에는 예외처리를 해주어야 한다. 출처 : http://blog.nextcube.pe.kr 큐(Queue) 큐는 스택과는 달리 먼저 들어간 데이터를 가장 먼저 출력하는 선입선출 (First In First Out)형식의 자료구조이다. 1. 1번 자료부터 순서대로 넣는다. 2. 1번부터 순서대로 출력한다
  • 9. 큐의 맨 앞의 출구에서 대기 중인 데이터를 Front라고 한다. 반대로 큐의 맨 마지막에서 대기 중인 데이터를 Rear라고 한다. 큐의 맨 앞에서 대기 중인 자료를 출력하는 것을 Dequeue();라고 하며, 큐 에 자료를 넣는 것을 Enqueue();라고 한다. 또한 아무것도 없는 큐에 Depueue();로 데이터를 출력하려는 경우 Queue Underflow라는 에러가 뜨며, 꽉 찬 큐에 Enpueue();로 데이터를 넣으려는 경우에도 Queue Overflow라는 에러가 뜬다. 이러한 큐는 크게 두 가지의 종류로 나눌 수 있다. 원형큐(순환큐), 링크드 큐가 바로 그것이다. 1.순환큐 Enqueue는 Rear에서만, Dequeue는 Front에서만 일어난다. 2.링크드 큐 링크드 큐는 위에서 예시로 들면서 설명한, 선형 구조의 큐이다. 출처 : http://lwove.egloos.com/2274841
  • 10. 백트래킹(Back Tracking) 백트래킹은 모든 조합을 시도해서 문제의 해를 찾는 방법이다. 백트래킹은 해를 얻을때까지 모든 경우의 수를 시도하기 때문에 언젠가는 반드시 그 답 을 찾아낸다. 백트래킹은 우선 모든 가능성을 나무처럼 구성할 수 있고, 나 무의 가지 중에 해결책이 이다. 백트래킹은 문제에서 요구하는 답을 무조건 내놓을 수 있다는 장점을 가지 고 있지만, 모든 경우의 수를 검사하기 때문에 시간이 오래 걸린다는 단점이 있다. 백트래킹에는 크게 두 가지 방법이 있는데, 우선 깊이 우선 탐색(Depth First Search)이 있다. 깊이 우선 탐색이란 가장 처음에서 가장 아래쪽까지 들어갔다가 더 이상 들어갈 곳이 없으면 위로 나와서 다른 곳으로 들어가고, 또 길이 없으면 다시 나와 다른 곳으로 들어가는 과정을 되풀이하여 답을 찾아 나가는 알고리즘을 말한다. 이 알고리즘은 스택을 사용하여 수현 할 수 있는데, 스택이 후입선출의 형식을 가진 자료구조이기 때문에, 깊이 들어갔 다가 바로 위로 나오는 것을 스택의 top을 빼는 것으로 간단하게 구현할 수 있기 때문이다. 또한 백트래킹에는 너비우선탐색(Breadth First Search)이라 는 방법도 존재한다. 너비우선탐색은 처음의 경우를 모두 조사하고, 답이 없다면 그 다음 깊이 (다음 단계)의 경우의 수를 모두 조사하고, 거기에도 답이 없다면 그 다음으 로 넘어가는 식으로 우선 한 라인을 모두 탐색하고 답이 없다면 다음 라인 으로 넘어가는 방식이다. 이 방법은 큐를 이용하여 구현할 수 있다. 출처 : http://blog.naver.com/dimigozzang/110122521040 Infix expression(중위 표기법) 중위표기법이란 우리가 가장 흔하게 쓰는 수식이다. 연산자가 피연산자와 피연산자 사이에 존재하는 수식으로 a+2 같은 형태의 수식이다. Postfix expression(후위 표기법) 후위표기법이란 연산자가 피연산자 뒤에 들어가는 수식이다. a 2 + 의 형 태의 수식이며, 중위표기법과 달리 괄호를 쓸 필요가 없으므로 연산의 효율 성이 높아진다.
  • 11. Infix → Postfix 중위 표기법을 후위 표기법으로 바꾸기 위해서는 Stack을 이용한다. 기본적인 변환 알고리즘은 아래와 같다. 1. ‘(’를 만나면 무시하고 넘긴다. 2. 피 연산자를 만나면 그대로 출력한다 3. 연산자를 만나면 스택에 Push한다. 4. ‘)’를 만나면 스택에서 Pop하여 출력한다. 예를 들어 (a+b)*c+d*k 라는 수식을 위의 알고리즘을 참고하여 후위표기법 으로 변환한다고 하자. 우선 표시할 수 있는 모든 괄호를 표시하자. 그러면 저 수식을 ((a+b)*c)+(d*k) 로 나타낼 수 있다. a는 피연산자 이므로 그대 로 출력하고, 그 다음 나오는 +는 연산자이므로 스택에 푸시 한다. 다음에 나오는 b 역시 피연산자이므로 그대로 출력하며, 그리고 )가 나오므로 스택 에 저장되어있던 +를 꺼내온다. 이런 식으로 알고리즘을 따라가면 저 수식이 후위 표기법으로 a b + c * d k * + 로 나타 낼 수 있다. 출처 : http://blog.naver.com/ryutuna/100122313091 http://blog.naver.com/checkdisk/110104634673
  • 12. 알고리즘 1 말의 여행 알고리즘 1. 처음 초기위치는 모두 0으로 초기화 시켜준다. 2. 처음 위치에서 이동하면서 갈림길을 발견하면 0은 갈 수 있는 길...ㄱ. 1은 갈 수 없는 길...ㄴ. ㄱ.갈 수 있는 길은 계속 진행한다. ㄴ.갈 수 없는 길이므로 원래 자리로 돌아온다. → 백트래킹 3. 규칙을 기본으로 자리이동시의 좌표 값을 저장한다.→스택 ※스택 LIFO : Last In First Out 같은 타입의 집합을 관리. push : 자료를 집어넣는 행위. pop : 자료를 빼 내는 행위. push의 동작 -push로 데이터를 넣으며, push 함수에선 top을 1 증가시킴. -top을 인자로 가지는 배열에 입력 data를 넣음. -top과 할당된 스택의 크기를 비교하여 top이 스택의 마지막 요소보다 작을 때만 push. -이 조건에 맞지 않으면 에러를 리턴.(오버플로우) pop의 동작 -Top 위치의 값을 읽고 Top은 하나 감소. -스택이 텅 비어서 더 꺼낼 데이터가 없을 때 -1이라는 에러 리턴.(언더플 로우) 4. 출력 시는 스택으로 저장한 입력 값은 큐로 출력.
  • 13. 알고리즘 2 일차원 배열을 이용한 말의여행 소스 구현 알고리즘 ①말의 좌표를 십진수 화 시킨다. ②말이 해당하는 좌표에서 갈 수 있는 여덟 가지 경우를 계산한다. ③계산 한 값 중 장기판 내부에 있는 제일 작은 수의 경우를 스택배열에 저 장한다. ④제일 작은 수의 경우에 갈 수 있는 여덟 가지 경우를 다시 계산해준다. ⑤또 다시 나온 제일 작은 수의 경우를 스택에 저장해준다. ⑥만일 스택에 저장하는 과정에서 중복되는 경우가 있으면 다시 그 앞에 저 장된 값으로 돌아간다.→백트래킹 ⑦돌아간 값은 앞에서 중복되었던 경우를 skip하고 다른 경우의 수를 저장한 다. (0,0)을 입력 한다고 가정하면, 제일 작은 숫자들이 배열에 담기게 된다. . . . . . . . . . . . 2,4 ←밑의 수들과 같은 방식으로 들어간 다른 값. 1,2 ←계산된 제일 작은 십진수화 된 좌표 값. 0,0 ←(0,0)부터 담기게 됨.
  • 14. 최종 알고리즘 1차 배열 또는 2차 배열을 사용해 장기판을 만든 뒤 말이 움직이는 좌표로 가는 배열을 생성하여 상황에 맞게 말을 움직인다. 2차 배열일 경우에는 ①말의 좌표를 2차 배열로 표현한다. ②x와 y가 갈 수 있는 여덟 가지 경우를 입력한 배열의 값을 더해 말의 다 음 이동값을 계산한다. ③계산한 값을 스택에 넣는다. ④스택에 계산한 값이 있을 때 Pop한다. ⑤Pop을 한 경우에는 다른 값을 스택에 넣는다. 1차 배열일 경우에는 ①말의 좌표를 십진수 화 시킨다. ②말이 해당하는 좌표에서 갈 수 있는 여덟 가지 경우를 계산한다. ③계산 한 값 중 장기판 내부에 있는 제일 작은 수의 경우를 스택배열에 저 장한다. ④제일 작은 수의 경우에 갈 수 있는 여덟 가지 경우를 다시 계산해준다. ⑤또 다시 나온 제일 작은 수의 경우를 스택에 저장해준다. ⑥만일 스택에 저장하는 과정에서 중복되는 경우가 있으면 다시 그 앞에 저 장된 값으로 돌아간다.→백트래킹 ⑦돌아간 값은 앞에서 중복되었던 경우를 skip하고 다른 경우의 수를 저장한 다. (0,0)을 입력 한다고 가정하면, 제일 작은 숫자들이 배열에 담기게 된 다. . . . . . . .
  • 15. . . . . 2,4 1,2 0,0 ←밑의 수들과 같은 방식으로 들어간 다른 값. ←계산된 제일 작은 십진수화 된 좌표 값. ←(0,0)부터 담기게 됨. 5)소스 구현 알고리즘 1에 대한 소스 #include <stdio.h> #define X 9 #define Y 8 #define MOVE 8 int board[X][Y]; int stack[180]; int mvx[MOVE] = {-2, -1, 1, 2, 2, 1, -1, -2}; int mvy[MOVE] = {1, 2, 2, 1, -1, -2, -2, -1}; int push(int i, int move); int pop(int i); int check(int a, int x, int y); int main(void) { int a=0, x, y, i, j=0; reset: scanf("%d %d", &x, &y); for(i=0; i<180; i++) stack[i]=-1;
  • 16. if(x < 0 || x > X || y < 0 || y > Y) { printf("다시 입력하시오"); goto reset; } for(i=0; i<180;) { push(i, x); push(i+1,y); for(;j<MOVE;) { up: x+=mvx[j]; y+=mvy[j]; if(x<0 || x>X || y<0 || y>Y) { x-=mvx[j]; y-=mvy[j]; j=(j+1)%8; goto up; } j=(j+1)%8; break; } if(check(a, x, y)==1) { pop(i); } i+=2; } for(i=0; i<180;)
  • 17. { printf("(%d,%d)", stack[i], stack[i+1]); i+=2; } return 0; } int push(int i, int move) { stack[i]=move; } int pop(int i) { return i-=2; } int check(int a, int x, int y) { for(a=0; a<180;) { if(stack[a]==x && stack[a+1]==y) { return 1; break; } a+=2; } } 알고리즘 2에 대한 소스 #include<stdio.h> int main() { int stack[90]; int x1[2]={-10,10},x2[2]={-20,20}; int y1[2]={-2,2},y2[2]={-1,1};
  • 18. int a,b,i=0,j,out,x,y; scanf("%d %d",&x,&y); a=x,b=y; //for( for(i=0;i<90;) { //말이 갈 수 있는 8가지 모든 경우의 수 a=x1[0]+a; b=y1[0]+b; if(b>=10 || a<=0 || b<=0) { a=a-x1[0]; b=b-y1[0]; } else { stack[i]=a+b; i++; a=x,b=y; } a=x1[0]+a; b=y1[1]+b; if(b>=10 || a<=0 || b<=0) { a=a-x1[0]; b=b-y1[1]; } else
  • 19. { stack[i]=a+b; i++; a=x,b=y; } a=x1[1]+a; b=y1[0]+b; if(b>=10 || a<=0 || b<=0) { a=a-x1[1]; b=b-y1[0]; } else { stack[i]=a+b; i++; a=x,b=y; } a=x1[1]+a; b=y1[1]+b; if(b>=10 || a<=0 || b<=0) { a=a-x1[1]; b=b-y1[1]; } else { stack[i]=a+b; i++; a=x,b=y; } a=x2[0]+a; b=y2[0]+b;
  • 20. if(b>=10 || a<=0 || b<=0) { a=a-x2[0]; b=b-y2[0]; } else { stack[i]=a+b; i++; a=x,b=y; } a=x2[0]+a; b=y2[1]+b; if(b>=10 || a<=0 || b<=0) { a=a-x2[0]; b=b-y2[1]; } else { stack[i]=a+b; i++; a=x,b=y; } a=x2[1]+a; b=y2[0]+b; if(b>=10 || a<=0 || b<=0) { a=a-x2[1]; b=b-y1[0]; } else { stack[i]=a+b;
  • 21. i++; a=x,b=y; } a=x2[1]+a; b=y2[1]+b; if(b>=10 || a<=0 || b<=0) { a=a-x2[1]; b=b-y2[1]; } else { stack[i]=a+b; i++; a=x,b=y; } /*for(j=0;j<i;j++) { printf("i=%d stack=%dn",i,stack[j]); }*/ a=(int)stack[0]/10; //경우의 수 중에 스택의 맨 위 쪽에 저 장 된 부분을 각각 x,y 좌표에 저장함. b=stack[0]%10; x=a,y=b; printf("a=%d b=%dn",a,b); for(j=0;j<=i;j++) { stack[j]=stack[j+1]; } } /*for(j=0;j<i-1;j++) {
  • 22. printf("%dn",stack[j]); }*/ //i=0; /*while(1) { if(i>90) { break; } else { printf("%dn",stack[i]); i++; } }*/ /*} for(j=0;j<i;j++) { printf("i=%d stack=%dn",i,stack[j]); }*/ } 1)문제점 : 갱신은 성공 하였으나, 첫 번째 여행을 끝마친 후 그 뒤의 여행 에서 자료 갱신이 안 되며 이미 지나간 길인지 검사가 되지 않음. #include<stdio.h> int main() { int stack[90]; int x1[2]={-10,10},x2[2]={-20,20}; int y1[2]={-2,2},y2[2]={-1,1}; int a,b,i=1,j=0,o,x,y;
  • 23. scanf("%d %d",&x,&y); a=x,b=y; stack[0]=a+b; up: while(1) { a=x,b=y; //말이 갈 수 있는 8가지 모든 경우의 수 a=-10+a; b=-2+b; if(b>=10 || a<=0 || b<=0 || a<10) { a=a-(-10); b=b-(-2); } else { stack[i]=a+b; break; //각 경우의 수의 경우 스택에 저장이 되면 바 로 포문을 빠져 나오도록 설계⟶가장 작은 수를 스택에 저장하고 더 이상 검색하지 않음. } a=-10+a; b=2+b; if(b>=10 || a<10 || a<=0 || b<=0) { a=a-(-10); b=b-2; }
  • 24. else { stack[i]=a+b; break; } a=10+a; b=-2+b; if(b>=10 || a<10 || a<=0 || b<=0) { a=a-10; b=b-(-2); } else { stack[i]=a+b; break; } a=10+a; b=2+b; if(b>=10 || a<10 || a<=0 || b<=0) { a=a-10; b=b-2; } else { stack[i]=a+b; break; } a=-20+a;
  • 25. b=-1+b; if(b>=10 || a<10 || a<=0 || b<=0) { a=a-(-20); b=b-(-1); } else { stack[i]=a+b; break; } a=-20+a; b=1+b; if(b>=10 || a<10 || a<=0 || b<=0) { a=a-(-20); b=b-1; } else { stack[i]=a+b; break; } a=20+a; b=-1+b; if(b>=10 || a<10 || a<=0 || b<=0) { a=a-20; b=b-(-1); } else {
  • 26. stack[i]=a+b; break; } a=20+a; b=1+b; if(b>=10 || a<10 || a<=0 || b<=0) { a=a-20; b=b-1; } else { stack[i]=a+b; break; } } printf("i=%d",i); /*for(o=0;o<i-1;o++) { if(stack[o]!=stack[i-1]) { x=(int)stack[i-1]/10,y=stack[i-1]%10; j=2; printf("stack=%d",stack[i-1]); goto up; // 가장 작은 수를 저장 한 후 그 수가 스택에 원래 존재하는지 안하는지를 판별 후 존재하지 않으면 x,y 좌표에 가장 마지막에 저장된 스택을 저장하고 다시 포문 함수를 불러냄. break; } else if(stack[o]==stack[i-1])
  • 27. { j=1; stack[i-1]='0'; } /*else if(stack[i-1]==stack[o]) { break; }*/ //} for(o=0;o<i;o++) { printf("stack=%dn",stack[o]); } /*printf("%dn",j); printf("x=%d y=%d",x,y); **?/ /*a=(int)stack[1]/10; b=stack[1]%10; x=a,y=b; printf("a=%d b=%dn",a,b); for(j=0;j<=i;j++) { stack[j]=stack[j+1]; } i=i-1; for(j=0;j<i;j++) { printf("%dn",stack[j]); }*/ }
  • 28. 최종소스 #include <stdio.h> // c+2=x번¹ø째A°의AC 좌AA표C¥ // ex) c=15면¸e 17번¹ø째A°의AC 좌AA표C¥ int main() { int a,b,c; scanf("%d %d",&a,&b); printf("1번¹ø째A° : %d,%dn",a,b); if(a==0&&b==0) { for(c=0; c<63; c++) { if(a<2&&b<8) { if(a%2==0||c==29) { a=a+1; b=b+2; printf("%d번¹ø째A° : %d,%dn",c+2,a,b); } // c=29는´A 원¿ø래·¡ 아¾Æ래·¡의AC 조A¶건°C(else)을A≫ 만¸¸족A·하CI지Ao만¸¸ 그±×렇·¸게°O 된μ E다´U면¸e 0,2로·I 중Aß복º¹이AI 되μC기±a 때¶§문¹�에¿¡ 다´U른¸¥ 방¹æ향Ca으A¸로·I 가°¡야¾ß 함 CO else if(c==44||c==62) { a=a+2; b=b+1; printf("%d번¹ø째A° : %d,%dn",c+2,a,b); } // c=44도μμ 물¹°론·Ð 아¾Æ래·¡의AC 조A¶건°C(else)을A≫ 만¸¸족A·하CI지Ao만¸¸ 그±×러·?면¸e 0,3 으A¸로·I 중Aß복º¹이AI 되μC기±a 때¶§문¹�에¿¡ 다´U른¸¥ 방¹æ향Ca으A¸로·I 가°¡야¾ß 함CO // c=62도μμ 물¹°론·Ð 아¾Æ래·¡의AC 조A¶건°C(else)을A≫ 만¸¸족A·하CI지Ao만¸¸ 그±×러·?면¸e 0,5 으A¸로·I 중Aß복º¹이AI 되μC기±a 때¶§문¹�에¿¡ 다´U른¸¥ 방¹æ향Ca으A¸로·I 가°¡야¾ß 함CO else { a=a-1; b=b+2; printf("%d번¹ø째A° : %d,%dn",c+2,a,b); } } else if(a<7&&b>7)
  • 29. { if(b%2==0) { a=a+2; b=b+1; printf("%d번¹ø째A° : %d,%dn",c+2,a,b); } else { a=a+2; b=b-1; printf("%d번¹ø째A° : %d,%dn",c+2,a,b); } } else if(a>6&&b>1) { if(a%2==0) { a=a-1; b=b-2; printf("%d번¹ø째A° : %d,%dn",c+2,a,b); } else { a=a+1; b=b-2; printf("%d번¹ø째A° : %d,%dn",c+2,a,b); } } else if((a>1&&b<2)||c==30||c==46) { if(b%2==0) { a=a-2; b=b+1; printf("%d번¹ø째A° : %d,%dn",c+2,a,b); } else if(c==15||c==30||c==46) { a=a-2; b=b+1; printf("%d번¹ø째A° : %d,%dn",c+2,a,b); } // 17번¹ø째A°가°¡ 되μC는´A c=15에¿¡서¼­ 일AI반¹Y적Au으A¸로·I 간°£다´U면¸e 0,0이AI 되μC서¼­ 중Aß복º¹이AI되μC기±a 때¶§문¹�에¿¡ 다´U른¸¥ 방¹æ향Ca으A¸로·I 가°¡야¾ß 함CO // 32번¹ø째A°가°¡ 되μC는´A c=30에¿¡서¼­ 일AI반¹Y적Au으A¸로·I 간°£다´U면¸e 1,5이AI 되μC서¼­
  • 30. 중Aß복º¹이AI되μC기±a 때¶§문¹�에¿¡ 다´U른¸¥ 방¹æ향Ca으A¸로·I 가°¡야¾ß 함CO // 48번¹ø재Ac가°¡ 되μC는´A c=46에¿¡서¼­도μμ 마¸¶찬Au가°¡지Ao로·I 일AI반¹Y적Au으A¸로·I 간° £다´U면¸e 1,6이AI 되μC서¼­ 중Aß복º¹이AI되μC기±a 때¶§문¹�에¿¡ 다´U른¸¥ 방¹æ향Ca으A¸로·I 가°¡야¾ß 함CO else { a=a-2; b=b-1; printf("%d번¹ø째A° : %d,%dn",c+2,a,b); } } else { a=a-1; b=b+2; printf("%d번¹ø째A° : %d,%dn",c+2,a,b); } // c=44에¿¡ 의AC하CI여¿ⓒ c=45는´A 위A§의AC 조A¶건°C이AI 하CI나³ª도μμ 성¼º립¸³하CI지Ao않 ¾E는´A 새≫o로·I운¿i 좌AA표C¥가°¡ 나³ª왔¿O기±a 때¶§문¹�에¿¡ 나³ª머¸O지Ao 경°æ우¿i에¿¡ 속¼O 한CN다´U. } // c=62 즉Ai 65번¹ø째A° 좌AA표C¥까±i지Ao의AC 움¿o직A÷임AO for(c=63; c<89; c++) { // c=63 즉Ai 65번¹ø째A° 좌AA표C¥부ºI터AI 시½A작AU if(a<4&&b<6) { if(a%2==0) { a=a+1; b=b+2; printf("%d번¹ø째A° : %d,%dn",c+2,a,b); } else { a=a-1; b=b+2; printf("%d번¹ø째A° : %d,%dn",c+2,a,b); } } else if(a<5&&b>5||c==69) { if(b%2==0||c==69) { a=a+2; b=b+1;
  • 31. printf("%d번¹ø째A° : %d,%dn",c+2,a,b); } // c=69에¿¡서¼­도μμ 정A¤상≫o적Au인AI 경°æ로·I로·I 움¿o직A÷인AI다´U면¸e 2,2가°¡ 되μC어¾i 중 Aß복º¹된μE 좌AA표C¥가°¡ 생≫y기±a므¹C로·I 다´U른¸¥방¹æ향Ca으A¸로·I 움¿o직A÷여¿ⓒ야¾ß 함 CO else { a=a+2; b=b-1; printf("%d번¹ø째A° : %d,%dn",c+2,a,b); } } else if(a>4&&b>3) { if(a%2==0) { a=a-1; b=b-2; printf("%d번¹ø째A° : %d,%dn",c+2,a,b); } else if(c==75) { a=a-1; b=b-2; printf("%d번¹ø째A° : %d,%dn",c+2,a,b); } // c=75는´A 원¿ø래·¡ 위A§의AC 조A¶건°C을A≫ 만¸¸족A·하CI지Ao만¸¸ 그±×러·?면¸e 6,4의AC 중 Aß복º¹된μE 좌AA표C¥가°¡ 생≫y기±a므¹C로·I 다´U른¸¥방¹æ향Ca으A¸로·I 이AI동μ¿한CN다´U. else if(c==84) { a=a-2; b=b+1; printf("%d번¹ø째A° : %d,%dn",c+2,a,b); } // c=84는´A 아¾Æ래·¡의AC 조A¶건°C을A≫ 만¸¸족A·하CI지Ao만¸¸ 그±×렇·¸게°O 된μE다´U면¸e 6,3 의AC 중Aß복º¹된μE 좌AA표C¥가°¡ 생≫y기±a므¹C로·I 다´U른¸¥방¹æ향Ca으A¸로·I 이AI동μ¿한CN다 ´U. else { a=a+1; b=b-2; printf("%d번¹ø째A° : %d,%dn",c+2,a,b); } } else if(a>3&&b<4) {
  • 32. if(b%2==0) { a=a-2; b=b+1; printf("%d번¹ø째A° : %d,%dn",c+1,a,b); } else if(c==88) //마¸¶지Ao막¸· 좌AA표C¥ { a=a-1; b=b+2; printf("%d번¹ø째A° : %d,%dn",c+2,a,b); } // c=88에¿¡서¼­는´A 움¿o직A÷일AI 곳°÷이AI 한CN곳°÷ 밖¹U에¿¡ 없¾ø기±a 때¶§문¹�에¿¡ 마¸¶지 Ao막¸· 좌AA표C¥로·I 이AI동μ¿한CN다´U. else { a=a-2; b=b-1; printf("%d번¹ø째A° : %d,%dn",c+1,a,b); } } else if(c==76) { a=a+2; b=b-1; printf("%d번¹ø째A° : %d,%dn",c+1,a,b); } // c=76은Aº 위A§의AC 조A¶건°C을A≫ 만¸¸족A·하CI는´A 곳°÷이AI 없¾ø기±a 때¶§문¹�에¿¡ 중Aß 복º¹된μE 좌AA표C¥를¸| 피CC하CI여¿ⓒ 다´U른¸¥ 곳°÷으A¸로·I 이AI동μ¿한CN다´U. } } return 0; }
  • 34. 6)문제점 파악/해결법 토의 현재 모든 소스에서 백트래킹이 실행되지 않고 있다. 길을 가다 막혔을 때 다른 방향으로 갈 수 있는 곳까지 백트래킹을 해야 하지만 한번 밖에 되지 않아 같은 값만 계속 출력하게 된다. 이 문제를 해결하기 위해 백트래킹과 스택에 대한 자료를 계속 찾아보고 다양한 방면으로 시도를 해보았으나 해 결되지는 않았다. 마지막 최종 소스에서는 이전과는 다른 방법으로 진행해보려 했으나 역시 백트래킹이 실행되지 않았다.