26
자료구조01 조별 프로젝트 #2 여행 여행 여행 여행 ( ) ( ) ( ) ( ) 조장 김창헌 : 09 조원 김정훈 : 09 김정무 11 김종진 11 김지환 11

Project#2말의여행 Hwp

Embed Size (px)

Citation preview

Page 1: Project#2말의여행 Hwp

자료구조01

조별 프로젝트 #2

말 의 여행말 의 여행말 의 여행말 의 여행( )( )( )( )

조장 김창헌: 09

조원 김정훈: 09

김정무11

김종진11

김지환11

Page 2: Project#2말의여행 Hwp

-Index--Index--Index--Index-

개인별 업무-

일정계획-

회의록-

기본자료-

알고리즘-

초안-

문제점 해결방안- &

최종소스-

결과분석-

참고문헌 및 출처-

Page 3: Project#2말의여행 Hwp

개인별업무개인별업무개인별업무개인별업무※※※※

일정계획일정계획일정계획일정계획※※※※

김창헌09 조장 회의록작성 및 보고서 작성 일정 계획: ,

김정훈09 관련사항 조사 및 복잡도계산

김정무11 관련사항 조사 및 복잡도계산

김종진11 프로그램 설계 및 알고리즘 구상

김지환11 프로그램 설계 및 알고리즘 구상

월 일3 27 업무분담 및 문제파악

월 일3 29 조사내용 정리 및 이해

월 일4 3 프로그램 설계 문제점 파악 해결방안 모색 및 초안작성

월 일4 7 최종 프로그램 설계 및 최종 보고서 작성

Page 4: Project#2말의여행 Hwp

회의록회의록회의록회의록※※※※회의일시회의일시회의일시회의일시 년 월 일 화년 월 일 화년 월 일 화년 월 일 화2012 3 27 ( )2012 3 27 ( )2012 3 27 ( )2012 3 27 ( ) 조조조조 C1 작성자작성자작성자작성자 김창헌09참석자참석자참석자참석자 김창헌 김정훈 김정무 김종진 김지환09 , 09 , 11 , 11 , 11

회의내용회의내용회의내용회의내용

내용내용내용내용 비고비고비고비고

조원별 업무분담조원별 업무분담조원별 업무분담조원별 업무분담1.1.1.1.조장과 프로그램설계 명 관련사항 조사 명으로 팀을 구성했다2 , 2 .일정 계획일정 계획일정 계획일정 계획2.2.2.2.다음 회의시간까지 자신이 맡은 업무를 수행해 와서 서로 어떻게 문제를 풀어나갈 것 인지 토의하기로 함보고서 계획보고서 계획보고서 계획보고서 계획3.3.3.3.소집단보고서작성 및 자신들이 참고한 자료들과 출처를 조장에게 보내주기로 함.조장이 종합해서 보고서 초안 작성하기로 함.알고리즘 계획알고리즘 계획알고리즘 계획알고리즘 계획4.4.4.4.다음 회의시간에 서로 맡은 업무에 충실히 연구를 하여 어떻게 알고리즘을 짤 것인지에 대해 토의하기로 함.

Page 5: Project#2말의여행 Hwp

회의일시회의일시회의일시회의일시 년 월 일 목년 월 일 목년 월 일 목년 월 일 목2012 3 29 ( )2012 3 29 ( )2012 3 29 ( )2012 3 29 ( ) 조조조조 C1 작성자작성자작성자작성자 김창헌09참석자참석자참석자참석자 김창헌 김정훈 김정무 김종진 김지환09 , 09 , 11 , 11 , 11

회의내용회의내용회의내용회의내용

내용내용내용내용 비고비고비고비고

조원별 업무 파악조원별 업무 파악조원별 업무 파악조원별 업무 파악1.1.1.1.각자 맡은 업무에 대해 조장이 자료들을 확인하여 프로젝트를 어떤 방향으로 진행해야할지 초안에 대해 토의함.일정 확인일정 확인일정 확인일정 확인2.2.2.2.회의시간이 끝나고 설계조원들이 초안을 작성한 뒤 주말에 모여서 프로젝트를 진행하기로 함.문제점 파악해결법 토의문제점 파악해결법 토의문제점 파악해결법 토의문제점 파악해결법 토의3. /3. /3. /3. /스택 큐 백트래킹의 기본적 내용만 알고 있어서 어떻게 프로그램에 적용시킬 것, ,인지에 대해 많은 연구가 필요할 것 같다.자료조사 하는 조원이 오늘밤까지 스택 큐 백트래킹의 종류와 적용법등을 조사, ,하여 온라인으로 설명을 해주기로 했다.보고서 초안 토의보고서 초안 토의보고서 초안 토의보고서 초안 토의4.4.4.4.개인 소집단 보고서와 자료조사내용 및 출처와 프로그램 초안과 알고리즘 프로,그램 설계중 문제점과 해결법을 추가하여 보고서 초안을 만들기로 토의함.

Page 6: Project#2말의여행 Hwp

회의일시회의일시회의일시회의일시 년 월 일 화년 월 일 화년 월 일 화년 월 일 화2012 4 3 ( )2012 4 3 ( )2012 4 3 ( )2012 4 3 ( ) 조조조조 C1 작성자작성자작성자작성자 김창헌09참석자참석자참석자참석자 김창헌 김정훈 김정무 김종진 김지환09 , 09 , 11 , 11 , 11

회의내용회의내용회의내용회의내용

내용내용내용내용 비고비고비고비고

조원별 업무 파악조원별 업무 파악조원별 업무 파악조원별 업무 파악1.1.1.1.자료조사 조원들은 임무를 거의 다 수행하여 설계조원의 임무를 같이 도와주기,로 하였음.일정 확인일정 확인일정 확인일정 확인2.2.2.2.이번 회의 마치고 설계 조원이 소스를 마무리하면 주말에 모여서 최종보고서 및소스파악 하기로 함.문제점 파악 해결법 토의문제점 파악 해결법 토의문제점 파악 해결법 토의문제점 파악 해결법 토의3. /3. /3. /3. /스택을 사용하지 않고 소스를 설계해서 관련사항 조원들과 함께 어떤 식으로 접목시켜야 할지 이야기 하기로 함.보고서 확정보고서 확정보고서 확정보고서 확정4.4.4.4.최종 소스 마무리 되고 나서 조원들과 모여 조장이 쓴 최종보고서를 읽어보고수정 할 부분 수정 하고 최종보고서 확정 짓기로 함

Page 7: Project#2말의여행 Hwp

기본자료기본자료기본자료기본자료※※※※스택의 개념스택의 개념스택의 개념스택의 개념

스택의 구조는 매우 간단합니다 스택은 밑이 막혀있는 긴 통이라고 보면 됩니다 즉 입구. . ,

와 출구가 같은 긴 통이므로 먼저 들어간 것은 밑에 있게 되고 나중에 들어간 것은 제일,

먼저 나오게 됩니다 그래서 스택을 구조라 고 합니다. LIFO(Last In First Out) .

스택을 조작하는 방법 연산이라고 합니다 은 두가지가 있습니다 하나는 스택에 값을 집( .) .

어 넣는 연산인 pushpushpushpush이고 다른 하나는 스택에서 값을 빼내는 poppoppoppop 동작입니다 위 그림을.

보면 쉽게 이해가 될 것입니다.

배열로 스택 구현하기배열로 스택 구현하기배열로 스택 구현하기배열로 스택 구현하기

배열을 이용하여 스택을 구현하는 것은 위의 그림과 같은 모양이 됩니다 우선 스택의 긴.

통을 정의 하고 스택의 마지막 데이터의 위치인 상단을 이라는 배열 인덱스를 이용하겠top

습니다.

배열의 성격상 스택 이라는 통의 크기는 정해 놓아야 합니다 일단 이라고 잡겠습니다. 10 .

스택에 들어갈 데이터는 정수형이라고 가정하면 다음과 같이 정의 할 수 있습니다.

스택의 크기 정의#define MAXSIZE 10 //

스택의 긴 통int stack[MAXSIZE]; //

스택의 상단int top; //

여기서 의 위치를 정확히 규정해 봅니다 어떤 경우는 이 스택의 가장 위 데이터가top . top

아니라 그 위 즉 다음에 들어갈 데이터 저장 공간을 가리키기도 합니다 여기서는 가장 위, , .

의 데이터를 가리키는 것으로 정하겠습니다 스택을 정의 할 때 두가지 중 하나를 선택해서.

사용하여야 하며 혼용되어서는 안됩니다, .

그리고 스택연산을 정의 할 때 극단적인 경우 즉 데이터가 하나도 없을 때와 꽉 차있을, , , ,

때에 약간 주의를 해야 합니다.

먼저 스택이 비어 있는 경우 은 의 값을 가져야 합니다 에서 배열의 인덱스는, top -1 . C 0

부터 시작하므로 이 이라면 스택에 데이터가 하나 있다는 의미입니다 스택이 비어있, top 0 .

는 경우는 초기 스택이 생성되었을 때도 마찬가지 이므로 스택을 초기화 하려면 을top -1

로 설정하면 됩니다.

를 위해서는 값이 있어야 하므로 의 함수 인자로 이라는 양의 정수형을 사용하push push val

겠습니다 그 후 는 을 하나 증가시키고 배열의 인덱스 에 을 넣으면 됩니다. push top top val .

그런데 앞서 말씀드렸듯이 스택이 꽉차있는 경우에 를 하게 되면 스택이 넘쳐나게 됩, push

니다 이를 스택 오버플로우 라고 합니다 그러므로 배열의 인덱스인 이. (Stack Overflow) . top

Page 8: Project#2말의여행 Hwp

이 되었을 때 스택이 꽉차있는 경우이므로 예외 처리를 해야 합니다MAX-1 .

스택의 용도스택의 용도스택의 용도스택의 용도[[ ]][[ ]][[ ]][[ ]]

컴퓨터에서 스택이 사용되는 가장 대표적인 부분은 바로 연산이다.

연산에는 우선 순위라는 것이 있기 때문에 연산 도중에 우선 순위가 높은 연산을 만나게 되면 그 동

안의 연산 결과를 잠시 보관해두고

우선 순위가 높은 연산을 먼저 처리하게 되는데 이때 또다시 더 높은 순위의 연산을 만나면 또 스택

에 보관해두고 현재의 연산을 한다.

그리고 순위가 높은 연산이 끝나면 다시 스택에서 그 전에 하던 연산을 가져와서 계속해서 연산을 수

행해 나가는 것이다.

이 것 이외에도 함수의 호출시에도 메인 함수에서 함수를 호출하게 되면 메인 함수에서 사용되던 지

역 변수들이 모두 스택에 저장된다.

그리고 해당 함수의 작업을 진행하게 되고 또 그 함수에서 다른 함수의 호출이 있게 되면 그 동안 사

용되던 모든 정보를 스택에 저장하고

다시 함수를 호출하여 작업을 수행하다가 그 함수가 종료되면 스택에서 그 전의 모든 정보를 가져와

함수 호출 다음의 작업을 재개한다.

이런 식의 작업들을 수행하기 위해서는 스택이라는 후입 선출의 기억 장치가 꼭 필요한 것이다.

큐의 개념큐의 개념큐의 개념큐의 개념

큐는 스택과 비슷한 모양을 하고 있지만 조작방식은 다릅니다 큐의 구조도 간단한데, . , 스

택과 달리 앞 뒤가 뚫린 통이라고 보시면 됩니다 이 통은 뒤에서 뭔가를 집어넣고 앞에서.

빼냅니다 즉 먼저 들어온 것은 먼저 나오는 구조로 이라고 부릅니. , FIFO(First In First Out)

다.

큐의 연산은 putputputput과 getgetgetget이 있습니다 큐에 자료를 집어 넣을 때는 뒤. (rearrearrearrear 에서 처리하고) ,

이를 putputputput이라고 합니다 반대로 큐에서 자료를 빼낼 때는 앞. (frontfrontfrontfront 에서 처리하고 이를) getgetgetget

이라고 합니다.

배열로 큐 구현하기배열로 큐 구현하기배열로 큐 구현하기배열로 큐 구현하기

배열을 이용한 큐의 구현은 스택의 구현과 비슷한 난이도일 것 같지만 조금 더 생각해보,

면 문제가 아주 많습니다 먼저 저장할 자료의 앞과 뒤를 가리키는 변수를 선언하여 큐의.

구조를 정의해 보겠습니다.

큐의 크기#define MAXSIZE 10 //

int queue[MAXSIZE];

int front=-1, rear=-1;

다음으로 과 연산을 정의해 보겠습니다put get .

int put (unsigned int val) {

Page 9: Project#2말의여행 Hwp

if (rear >= MAXSIZE-1) {

printf (" Queue Overflow");

return (-1);

}

queue[++rear] = val;

}

int get () {

if (front <= 0) {

printf (" Queue Underflow");

return -1;

}

return queue[front++];

}

배열의 인덱스로 사용되는 와 가 위 코드에서는 계속 증가하기만 합니다 결국 몇front rear .

번의 연산을 한 후에 가 배열의 한계를 넘어 더이상 연산이 에러를 발생시rear put Overflow

킬 수 있습니다 그러므로 가 배열의 한계에 다다랐을 때에 큐의 데이터를 배열의 앞부. rear

분으로 옮기는 동작이 필요하게 됩니다.

int put (unsigned int val) {

if (rear >= MAXSIZE-1) {

if (!(rear-front)) {

return -1;

}

여기서 배열의 앞으로 옮겨야 한다// .

memcpy (&queue[0], &queue[front], rear-front+1);

rear=rear-front;

front = 0;

}

queue[++rear] = val;

}

지금은 배열의 개수를 으로 정의 했지만 만약에 억개라면 그런 데이터 이동이 할10 5 ? put

때마다 발생한다면 당연히 비효율적이겠죠? .

그래서 해결방법으로 나왔습니다 환형 또는 원형 큐 를 이용하는 것입니. ( ) (Circular Queue)

다 환형 큐는 뱀이 꼬리를 물고 있는 듯한 모양을 가지고 있습니다 데이터가 순환하며 저. .

장되기 때문에 끝이라는 개념도 없습니다 다음 그림을 보시죠. .

큐의 용도큐의 용도큐의 용도큐의 용도[[ ]][[ ]][[ ]][[ ]]

큐는 일련의 일들이 순차적으로 진행되는 가운데 일의 진행이 조금 지체될때 큐에는 다음 일들이 계,

속해서 쌓여가는 방식이다.

흔히 버퍼링이라 불리는 스트리밍의 로딩 작업 역시 큐에 자료가 쌓이고 플레이어는 큐의 앞부분부터

플레이를 하게 되는 것이다.

그러다 로딩이 늦어져서 큐에 쌓였던 자료가 모두 사용되고 나면 플레이어는 중지되고 다시 버퍼링

작업을 하게 되는 것이다.

이것 이외에도 프린트 작업을 할때 프린터는 처리 속도에 제한이 있기 때문에 여러가지의 출력을 지

시하게 되면 지시된 순서대로

큐에 자료를 저장하고 하나의 출력이 끝나면 큐에서 다음 자료를 받아와 출력하는 작업을 반복한다.

그러다 큐가 비면 대기 상태가 된다.

이외에도 큐의 용도는 다양하다 기억할 점은 큐는 순차적인 업무 처리를 위해 다음 할 일을 기억해.

두는 장치라는 것이다.

Page 10: Project#2말의여행 Hwp

스택은 하던 일을 잠시 접어둘때 사용되는 기억 장치라는 점이 큐와는 다른 점이다.

백트래킹백트래킹백트래킹백트래킹

입력받은 배열의 값에 대해서 가능한 모든 순서조합을 만들어냅니다.

단 모든 순서조합을 위해서는 최초에 배열의 수가 오름차순으로 정렬되어져 있어야 합니,

다.

최종적인 형태는 내림차순정렬이 되어져 있으며 이때 함수는 더이상 처리를 하지 않고 들,

어온 값 그대로 리턴 시켜 버립니다.

내림차순 정렬이 완료 되었으나 맞는 조합이 없었다면 해당 문제는 해가 없는 것이 됩니, ,

다.

매번 시도 마다 다음 조합으로 만들어 냅니다 차 배열만 배열의 크기는 무관. (1 , )

현재 배열의 순서가 답이 될수 없다면 배열을 다시 백트랙 돌리면 바로 다음 배열 순서의,

조합을 만들어냅니다.

의 항이 있었다고 가정할 때 이 값의 순서가 해당 문제의 답으로서1-2-3-4-5-6-7-8-9 ,

맞지 않는다면 다음 항으로는 한칸 앞으로 돌아와서 순서를 바꾸어 볼수 있습니다.

입력받은 배열의 값에 대해서 가능한 모든 순서조합을 만들어냅니다.

단 모든 순서조합을 위해서는 최초에 배열의 수가 오름차순으로 정렬되어져 있어야 합니,

다.

최종적인 형태는 내림차순정렬이 되어져 있으며 이때 함수는 더이상 처리를 하지 않고 들,

어온 값 그대로 리턴 시켜 버립니다.

내림차순 정렬이 완료 되었으나 맞는 조합이 없었다면 해당 문제는 해가 없는 것이 됩니, ,

다.

매번 시도 마다 다음 조합으로 만들어 냅니다 차 배열만 배열의 크기는 무관. (1 , )

현재 배열의 순서가 답이 될수 없다면 배열을 다시 백트랙 돌리면 바로 다음 배열 순서의,

조합을 만들어냅니다.

Page 11: Project#2말의여행 Hwp

중위표기법 전위표기법 후위표기법infix, prefix, postfix. ( , , )

일반적인 수식은 이다infix .

즉 연산자가 피연산자 보통숫자나 문자 와 피연산자 사이에 존재한다 과 같은 형태, ( ) . a + 1

이다.

기준이 되는 것은 연산자의 위치이다.

과 같이 연산자가 피연산자들 앞에 있다면 라고 한다+ a 1 prefix .

반대로 과 같은 경우는 당연히 라고 한다a 1 + postfix .

그럼 를 로 바꾸는 법을 알아보자infix prefix or postfix .

우선 식을 하나 가져온다infix .

1 + ( a + 2 ) * 5 / 7

아무렇게나 쓴 식이다.

이 식에서 취할 수 있는 모든 괄호를 취해보자.

( 1 + ( ( ( a + 2 ) * 5 ) / 7 ) )

계산상의 순서의 변화는 없을 것이다 그저 보조괄호를 취한 것뿐이니. .

여기서 주목할 것은 각 괄호 안에는 모두 피연산자 연산자 피연산자 의 구조를 갖고, " + + "

있다는 것이다.

각 괄호를 기준으로 연산자를 뒤로 빼보자.

( 1 + ( ( ( a 2 )+ * 5 ) / 7 ) )

( 1 + ( ( ( a 2 )+ 5 )* / 7 ) )

( 1 + ( ( ( a 2 )+ 5 )* 7 ) / )

( 1 ( ( ( a 2 )+ 5 )* 7 ) / ) +

각 연산자가 자기 자신이 속해 있는 괄호의 뒤로 빠진 것이다.

이런 식으로 바꾸고 괄호를 모두 삭제해보자.

1 a 2 + 5 * 7 / +

위와 같은 모양의 식이 나오는데 이게 제대로 만들어 진 건지를 확인해 보기 위해서,

이 상태로 앞에서 부터 스택에 넣고 계산해 보자 연산자를 만나면 스택에서 두개의 피연산.

자를 빼서 계산하고 다시 넣는다.

+ : a + 2

* : (a + 2 ) * 5

/ : (a + 2 ) * 5 / 7

+ : 1 + ( a + 2 ) * 5 / 7

잘 된다.

그렇다면 는 위의 괄호에서 연산자를 앞으로 빼면 된다prefix ? .

의 경우에는 헝가리 표기법이라고도 한다는데 원래는 명제를 단순하게 표현하기 위해prefix

서 씌였다고 한다.

Page 12: Project#2말의여행 Hwp

이를 가지고 스택으로 계산이 불가능한가?

그건 또 아니다 단지 구현의 차이일뿐. .

에서 연산자를 만나면 스택에서 두개의 피연산자를 빼서 더하고 다시 넣어줬다면postfix ,

에서는 만약에 스택에 연속 된 두개의 피연산자가 들어오면 두개의 피연산자를 빼주prefix

고 바로 밑의 연산자를 꺼내

계산을 하고 이를 집어 넣어 준다.

예를 보는 게 가장 빠르겠지...

( a + b ) * c + d * k

물론 아무렇게나 쓴 식이다.

괄호로 묶는다.

( ( ( a + b ) * c ) + ( d * k ) )

변환 한다.

( ( + ( a b ) * c ) + ( d * k ) )

( * ( + ( a b ) c ) + ( d * k ) )

( * ( + ( a b ) c ) + * ( d k ) )

+ ( * ( + ( a b ) c ) * ( d k ) )

괄호 제거...

+ * + a b c * d k

와 같다 이제 하나씩 넣어보자 초반에는 연산자만 잔득이나 한번에 넣었다고 하자 일일이. . .

한줄씩 쓰기 귀찮으니.

개의 연산자와 개의+ * + a : b -> + * ( a + b ) // 3 1

피연산자가 있는데 추가로 한개의 피연산자 삽입

+ * ( a + b ) : c -> + ( ( a + b ) * c )

+ ( ( a + b ) * c ) : * -> + ( ( a + b ) * c ) *

+ ( ( a + b ) * c ) * : d -> + ( ( a + b ) * c ) * d

+ ( ( a + b ) * c ) * d : k -> + ( ( a + b ) * c ) (d * k) - > ( ( a + b ) *

c ) + (d * k)

잘 된다~

각 표기법을 자료구조를 통해서 바꾸는 법.

트리 형태< >

가장 먼저 연산 되는 것부터 리프에서 부터 만들어서 타고 올라온다.

이를 전위 순회를 하면 후위 순회를 하면 중위 순위를 하면 가 된다prefix, postfix infix .

형태를 만들면 스택을 이용하여 가능하다, .

Page 13: Project#2말의여행 Hwp

스택과 큐를 사용< >

요건 좀 중요한데 우선 을 로 만드는 방법을 보자, infix postfix .

스택과 큐를 사용한다 스택은 를 로 바꾸는 과정에서 연산자를 잠시 저장한다. infix postfix .

알고리즘은 아래와 같다.

각 연산자의 우선순위는 괄호 의 순이다[ < +,- < *,/ ] .

를 만나면 스택에 푸시한다 푸시 저장1. '(' . ( => )

를 만나면 스택에서 가 나올때까지 팝하여 큐에 넣고 는 팝하여 버린다2. ')' '(' '(' .

연산자를 만나면 스택에서 그 연산자보다 낮은 우선순위의 연산자를 만날 때까지 팝하3.

여 큐에 넣고 자신을 푸시한다.

피연산자는 그냥 큐에 넣는다4. .

모든 입력이 끝나면 스텍에 있는 연산자들을 모두 팝하여 출력한다5. .

예) (2*(3+6/2)+2)/4+3

문자 큐 스택 상단 하단 설명( -> )

( (

스택에 푸시 저장'(' ( )

2 2 (

숫자는 화면에 출력

* 2 * ( '*'

가 보다우선순위가 높음'('

( 2 ( * ( '('

는 스택에 푸시 저장( )

숫자3 2 3 ( * (

는 화면에 출력

가+ 2 3 + ( * ( '+'

보다 우선순위가 높음'('

숫자6 2 3 6 + ( * (

는 화면에 출력

가/ 2 3 6 / + ( * ( '/'

보다 우선순위가 높음'+'

숫자2 2 3 6 2 / + ( * (

는 화면에 출력

까지) 2 3 6 2 / + * ( '('

는 팝하여 출력 는무시,'('

는+ 2 3 6 2 / + * + ( '*'

보다 높으므로 팝'+'

숫자는2 2 3 6 2 / + * 2 + (

출력

까지 팝) 2 3 6 2 / + * 2 + '('

하여 출력

연산자는/ 2 3 6 2 / + * 2 + /

푸시 저장( )

Page 14: Project#2말의여행 Hwp

숫자는 출4 2 3 6 2 / + * 2 + 4 /

는 보다+ 2 3 6 2 / + * 2 + 4 / + '/' '+'

높아서 출력하고 는저장'+'

숫자는 출3 2 3 6 2 / + * 2 + 4 / 3 +

끝 끝이므로 모두2 3 6 2 / + * 2 + 4 / 3 +

팝 출력( )

이제 큐에 있는 내용을 디큐 하면서 스택에 넣으면서 위에 정리한 방법으로(dequeue) postfix

계산을 하면 된다.

Page 15: Project#2말의여행 Hwp

알고리즘알고리즘알고리즘알고리즘※※※※장기판 좌표를 정수로 바꾸었을 경우1) .

말의 좌표 를 입력한다x, y .①

를 통해 각 좌표를 정수로 바꾸고 차 배열로 구현하고 으로 초기화한다x*10+y 1 0 .②

한 번 간 좌표는 로 표시하여 중복을 피한다1 .③

움직일 때 마다 카운트를 올린다.④

움직일 곳 없이 모두 막혀 있다면 백트랙킹을 통해 다음 조건을 찾아본다.⑤

반복한다.⑥

카운터가 장기판 크기인 까지 올라왔다면 처음부터 출력한다89 .⑦

장기판 좌표를 정수로 바꾸었을 경우 수정1-1) ( ).

말의 좌표 를 입력한다x, y .①

를 통해 각 좌표를 정수로 바꾼다x*10+y .②

말이 움직인 좌표를 배열에 넣는다stack .③

움직일 때 마다 카운트를 올린다.④

말이 있는 좌표에서 이동 가능한 전 좌표를 찾는다.④

스택 배열에 들어있는 좌표와 번에서 찾은 좌표를 처음부터 비교해 순서대로 중복되지⑥ ④

않았다면 첫 번째 좌표를 배열에 넣고 계속 반복한다stack .

움직일 곳 없이 모두 막혀 있다면 백트랙킹을 통해 다음 조건을 찾아본다.⑤

반복한다.⑥

카운터가 장기판 크기인 까지 올라왔다면 처음부터 출력한다89 .⑦

장기판 좌표를 정수로 바꾸엇을 경우 수정1-2) ( ).

말의 좌표 를 입력한다x, y .①

를 통해 각 좌표를 정수로 바꾼다x*10+y .②

개 잡는다stack 2 .②

에 시작값을 저장stack1 .③

에 이동경로를 저장stack2 .④

의 의 값으로 이동stack2 top .④

의 의 값의 이동경로에 의 값이 포함되지 않는다면 에 의 값을stack2 top stack1 stack1 top⑥

버림.

의 의 값이 이동경로에 의 값이 포함된다면 의 의 값을stack2 top stack1 stack2 top stack1⑤

에 저장.

의 의 값을 버림stack2 top .⑥

에 값이 없을 경우 의 배열을 의 형태로 좌표 출력stack2 stack1 queue .⑦

에 값이 있을 경우 에 저장된 값과 비교 후 에 없는 이동경로만stack2 stack1 stack1⑧

에 저장 중복체크stack2 ( )

번으로 돌아가서 반복⑨④

장기판을 차 배열로 구현했을 경우2) 2 .

말의 좌표 를 입력한다x, y .①

장기판의 각 점을 좌표라 생각하고 차 배열로 장기판을 만든다2 .②

한 번 간 좌표는 로 표시하여 중복을 피한다1 .③

움직일 때 마다 카운트를 올린다.④

Page 16: Project#2말의여행 Hwp

움직일 곳 없이 모두 막혀 있다면 백트랙킹을 통해 다음 조건을 찾아본다.⑤

반복한다.⑥

카운터가 장기판 크기인 까지 올라왔다면 처음부터 출력한다89 .⑦

Page 17: Project#2말의여행 Hwp

초안초안초안초안※※※※#include <stdio.h>

#include <stdlib.h>

#define ROW_SIZE 10

#define COL_SIZE 9

#define NUM_WAYS 8

typedef int board_t[ROW_SIZE][COL_SIZE];

int dr[NUM_WAYS] = {-2,-1,1,2,2,1,-1,-2};

int dc[NUM_WAYS] = {1,2,2,1,-1,-2,-2,-1};

void initialize_board(board_t board)

{

int i,j;

for(i=0;i<ROW_SIZE;i++)

{

for(j=0;j<COL_SIZE;j++)

{

board[i][j] = -1;

}

}

}

void print_board(board_t board)

{

int i,j;

for(i=0;i<ROW_SIZE;i++)

{

for(j=0;j<COL_SIZE;j++)

{

printf("%d\t",board[i][j]);

}

printf("\n");

}

}

int is_inside_board(int r, int c)

{

return r>=0 && r<ROW_SIZE && c>=0 && c<COL_SIZE;

}

int is_available(board_t board, int r, int c)

{

Page 18: Project#2말의여행 Hwp

return is_inside_board(r,c) && board[r][c] == -1;

}

int num_next_moves(board_t board, int r, int c)

{

int i,result=0;

for(i=0;i<NUM_WAYS;i++)

{

if(is_available(board,r+dr[i],c+dc[i]))

{

result++;

}

}

return result;

}

int next_way_of(board_t board, int r, int c)

{

int i, min = NUM_WAYS, result=0;

for(i=0;i<NUM_WAYS;i++)

{

if(is_available(board, r+dr[i], c+dc[i]) &&

num_next_moves(board,r+dr[i],c+dc[i])<min)

{

min=num_next_moves(board,r+dr[i],c+dc[i]);

result=i;

}

}

return result;

}

int main()

{

int r,c,move,next_way;

board_t board;

initialize_board(board);

while(1)

{

printf("input start position r(0~9) c(0~8): ");

scanf("%d %d",&r, &c);

fflush(stdin);

if(is_inside_board(r,c))

{

break;

}

printf("Please put them again.\n");

}

board[r][c] = 0;

Page 19: Project#2말의여행 Hwp

for(move=1;move<ROW_SIZE*COL_SIZE;move++)

{

if(num_next_moves(board,r,c)==0)

{

printf("Failed.\n");

print_board(board);

system("pause");

return 1;

}

next_way = next_way_of(board,r,c);

r=r+dr[next_way];

c=c+dc[next_way];

board[r][c]=move;

}

print_board(board);

system("pause");

return 0;

}

Page 20: Project#2말의여행 Hwp

문제점 해결방안문제점 해결방안문제점 해결방안문제점 해결방안&&&&※※※※

문제점

체스의 말 이동 소스를 참고해서 수정해 나

갔지만 그것은 장기의 말 이동과는 다른 이동

을 보여주고 스택을 사용하지 않고 공식을 이

용해 문제를 풀어 나갈려고 했다.

해결방안

스택을 이용한 차 배열로 바꿔 해결하려고1

했다.

Page 21: Project#2말의여행 Hwp

최종소스최종소스최종소스최종소스※※※※

#include <stdio.h>

#define STACK_SIZE 8

#define JANG_GI 89

int stack2[STACK_SIZE];

int po[STACK_SIZE47];

void position(int a){

int n, n1=0;

stack2[0] = a-21;

stack2[1] = a-19;

stack2[2] = a-12;

stack2[3] = a-8;

stack2[4] = a+8;

stack2[5] = a+12;

stack2[6] = a+19;

stack2[7] = a+21;

for(n=0; n<STACK_SIZE; n++){

if(stack2[n]<=0&&stack2[n]>=89){

if(stack2[n]%10==a%10-2||stack2[n]%10==a%10+2||stac

k2[n]%10==a%10+1||stack2[n]%10==a%10-1){

po[n1]=stack2[n];

n1++;

}

}

}

}

void stack(int a){

Page 22: Project#2말의여행 Hwp

int stack1[JANG_GI], stack3[JANG_GI];

int count=0, count1, top;

int k;

for(;;){

if(top==89){

break;

}

stack1[count]=a;

stack3[count]=a;

count++;

top++;

position(a);

for(count1=0; count1<=top; count++){

if(po[0]!=stack1[count1]){

a=po[0];

break;

}

else if(po[1]!=stack1[count1]){

a=po[1];

break;

}

else if(po[2]!=stack1[count1]){

a=po[2];

break;

}

else if(po[3]!=stack1[count1]){

a=po[3];

break;

}

else if(po[4]!=stack1[count1]){

a=po[4];

break;

}

Page 23: Project#2말의여행 Hwp

else if(po[5]!=stack1[count1]){

a=po[5];

break;

}

else if(po[6]!=stack1[count1]){

a=po[6];

break;

}

else if(po[7]!=stack1[count1]){

a=po[7];

break;

}

else{

top--;

count=top;

k=stack1[count+1]-stack3[count];

for(count1=0; count1<STACK_SIZE; count1++){

if(stack2[count]==k){

a = stack3[count]+stack2[count+1];

}

else{

break;

}

}

}

}

}

}

int main(){

int x, y, good;

int coor;

printf("input x:");

Page 24: Project#2말의여행 Hwp

scanf("%d", &x);

printf("input y:");

scanf("%d", &y);

coor = x*10+y;

stack(coor);

for(good=0; good<90; good++){

printf("<");

printf("%d", stack1[good]/10);

printf(",");

printf("%d", stack1[good]%10);

printf(">");

}

return 0;

}

Page 25: Project#2말의여행 Hwp

결과분석결과분석결과분석결과분석※※※※

좌표를 입력 받았지만 함수에서 오류가 나서 프로그램이 작동하지 않는다x, y stack .

Page 26: Project#2말의여행 Hwp

참고문헌 및 출처참고문헌 및 출처참고문헌 및 출처참고문헌 및 출처※※※※

URLURLURLURL

http://winplz.tistory.com/123

http://klsm1229.blog.me/150088201991

http://blog.naver.com/pjy9954?Redirect=Log&logNo=70128954403

http://blog.naver.com/skout123?Redirect=Log&logNo=50135743013

http://blog.naver.com/keloc?Redirect=Log&logNo=40153471559

http://blog.naver.com/dntkrl79?Redirect=Log&logNo=70095768962

http://blog.naver.com/keloc?Redirect=Log&logNo=40153471559

http://blog.naver.com/dntkrl79?Redirect=Log&logNo=70095768962

http://stackoverflow.com/questions/5633248/open-knights-tour-backtracking-algorithm-

in-smlnj

http://www.geeksforgeeks.org/archives/12916

http://blog.naver.com/ryutuna?Redirect=Log&logNo=100122313091

참고서적참고서적참고서적참고서적

-FOUNDATIONS OF ALGORITHMS USING C++ PSEUDOCODE p183~222p183~222p183~222p183~222

저Richard Neapolitan/kumarss Naimipour

언어로 배우는 자료구조-C p50~70p50~70p50~70p50~70