하노이 타워 : 재귀 알고리즘
재귀를 이해하는 데 아무런 문제가 없지만 하노이 타워 문제에 대한 재귀 솔루션에 대해 머리를 감쌀 수는 없습니다. 다음은 Wikipedia 의 코드입니다 .
procedure Hanoi(n: integer; source, dest, by: char);
Begin
if (n=1) then
writeln('Move the plate from ', source, ' to ', dest)
else begin
Hanoi(n-1, source, by, dest);
writeln('Move the plate from ', source, ' to ', dest);
Hanoi(n-1, by, dest, source);
end;
End;
단일 디스크를 이동할 수있을 때까지 기본 사례와 문제를 작은 조각으로 나누는 개념을 이해합니다. 그러나 기본이 아닌 경우의 두 재귀 호출이 함께 작동하는 방식을 알 수 없습니다. 누군가 나를 도울 수 있습니까? 감사.
실제로 해당 코드를 가져온 섹션 에서도 설명을 제공합니다.
n 개의 디스크를 페그 A에서 페그 C로 이동하려면 :
- n-1 개의 디스크를 A에서 B로 이동합니다. 그러면 peg A에서 디스크 #n 만 남습니다.
- 디스크 #n을 A에서 C로 이동
- n-1 개의 디스크를 B에서 C로 이동하여 디스크 #n에 배치합니다.
n 번째 디스크에 액세스 하려면 먼저 n -1 디스크를 제거해야합니다 . 그리고 전체 타워가 나타나기를 원하는 곳이 아닌 다른 말뚝으로 먼저 이동해야합니다.
게시물의 코드에는 디스크 수 외에 소스 페그, 대상 페그 및 디스크를 사이에 저장할 수 있는 임시 페그 (크기 n -1의 모든 디스크가 맞는 위치)의 세 가지 인수 가 있습니다 .
재귀는 실제로 두 번, 거기, 한 번 전에 writeln
, 한 번 발생합니다. 이전의 디스크는 대상 페그를 임시 저장소로 사용하여 n -1 개의 디스크를 임시 페그로 writeln
이동 합니다 (재귀 호출의 인수는 순서가 다릅니다). 그 후 나머지 디스크는 대상 페그로 이동하고 그 후에 두 번째 재귀는 n -1 타워를 임시 페그에서 디스크 n 위의 대상 페그 로 이동하여 전체 타워의 이동을 강제합니다 .
1 년 전에 함수형 프로그래밍 과정을 수강했고 알고리즘을 위해이 그림을 그렸습니다. 도움이 되길 바랍니다!
(0) _|_ | |
__|__ | |
___|___ | |
____|____ ____|____ ____|____
(1.1) | | |
__|__ | |
___|___ _|_ |
____|____ ____|____ ____|____ (A -> B)
(1.2) | | |
| | |
___|___ _|_ __|__
____|____ ____|____ ____|____ (A -> C)
(1.3) | | |
| | _|_
___|___ | __|__
____|____ ____|____ ____|____ (B -> C)
(2.1) | | |
| | _|_
| ___|___ __|__
____|____ ____|____ ____|____ (A -> B)
(3.1) | | |
| | |
_|_ ___|___ __|__
____|____ ____|____ ____|____ (C -> A)
(3.2) | | |
| __|__ |
_|_ ___|___ |
____|____ ____|____ ____|____ (C -> B)
(3.3) | _|_ |
| __|__ |
| ___|___ |
____|____ ____|____ ____|____ (A -> B)
3 개의 링 문제가 2 개의 2 개의 링 문제 (1.x 및 3.x)로 분할되었습니다.
http://www.cs.cmu.edu/~cburch/survey/recurse/hanoiimpl.html에 재귀 하노이 구현에 대한 좋은 설명이 있습니다.
요약하면 하단 플레이트를 스틱 A에서 스틱 B로 이동하려면 먼저 그 위에있는 모든 작은 플레이트를 A에서 C로 이동해야합니다. 두 번째 재귀 호출은 이동 한 플레이트를 C로 이동하는 것입니다. 베이스 케이스가 하나의 큰 플레이트를 A에서 B로 옮긴 후 다시 B로 돌아갑니다.
나는 이것이 당신이 그것을 처음 볼 때 즉각적인 것이 아니라는 것에 동의하지만, 당신이 그것을 내려 보면 상당히 간단합니다.
기본 사례 : 타워의 크기는 1입니다. 따라서 소스에서 목적지까지 한 번에 이동할 수 있습니다.
재귀적인 경우 : 타워의 크기는 n> 1입니다. 따라서 크기 n-1의 상단 타워를 추가 페그 (by)로 이동하고 크기 1의 하단 "타워"를 대상 페그로 이동 한 다음 상단 타워를 이동합니다. 에서 목적지까지.
따라서 간단한 케이스의 경우 높이 2의 타워가 있습니다.
_|_ | |
__|__ | |
===== ===== =====
첫 번째 단계 : 2-1 (= 1)의 상단 타워를 추가 페그 (중간 페그)로 이동합니다.
| | |
__|__ _|_ |
===== ===== =====
다음 : 하단 디스크를 대상으로 이동 :
| | |
| _|_ __|__
===== ===== =====
마지막으로 (2-1) = 1의 상단 타워를 목적지로 이동합니다.
| | _|_
| | __|__
===== ===== =====
생각해 보면 타워가 3 개 이상이더라도 항상 비어있는 추가 페그 또는 더 큰 디스크가있는 페그가있어 타워를 교체 할 때 재귀를 사용할 수 있습니다.
디스크를 A에서 C, B를 통해 이동한다고 가정합니다.
- 더 작은 디스크를 B로 이동합니다.
- 다른 디스크를 C로 이동합니다.
- B를 C로 이동합니다.
- A에서 B로 이동합니다.
- 모두 C에서 A로 이동합니다.
위의 모든 단계를 반복하면 디스크가 전송됩니다.
나는 고통을 느낀다!
이 글은 오래된 글이지만 정말로 이해해야 할 것은 "이것을 저것으로 옮기기"방식이 아니라 재귀의 부작용을 사용하는 것입니다.
저에게 귀중한 도움은 재귀 함수를 생각하고 작성하도록 가르치는 "The Little Schemer"였습니다.
그러나 이것은 독자가 다음 재귀 호출에서 반환 된 결과의 결과를 사용하도록 가르칩니다.
하노이 타워에서 답은 반환 된 결과 자체가 아니라 반환 된 결과의 관찰에 있습니다.
이 마법 은 함수 매개 변수의 연속적인 재 배열에서 발생합니다.
예, 문제는 실제로 세 부분으로 나뉩니다.
- 작은 타워를 여분의 못으로 옮기기
- 마지막 디스크를 대상 페그로 이동
- 예비 페그의 나머지 타워를 대상 페그로 이동합니다.
계획에서 :
(define (th n a b c)
(if (zero? n) 'done
(begin
(th (- n 1) a c b)
(display (list a c))
(newline)
(th (- n 1) b a c))))
(th 5 'source 'spare 'destination)
그러나 문제에 대한 해결책 인 함수 매개 변수를 표시하고 호출 구조와 같은 이중 트리를 결정적으로 이해합니다.
이 솔루션은 또한 기존의 제어 구조와 씨름 한 모든 프로그래머에게 힘 proof by induction
과 따뜻한 빛 을 전달합니다 .
덧붙여서, 손으로 문제를 해결하는 것은 상당히 만족 스럽습니다.
- 디스크 수를 세다
- 짝수 인 경우 첫 번째 디스크를 스페어 페그로 이동하고 다음 합법적 인 이동을 수행합니다 (상단 디스크 제외). 그런 다음 상단 디스크를 대상 페그로 이동하고 다음 법적 이동 (nittd)을 수행합니다. 그런 다음 상단 디스크를 소스 페그로 이동하고 다음 법적 이동 (nittd) ...
- 이상한 경우 첫 번째 디스크를 대상 페그로 이동하고 다음 합법적 인 이동을 수행합니다 (상단 디스크는 포함하지 않음). 그런 다음 상단 디스크를 여분의 페그로 이동하고 다음 법적 이동 (nittd)을합니다. 그런 다음 상단 디스크를 소스 페그로 이동하고 다음 법적 이동 (nittd) ...
항상 같은 손으로 상단 디스크를 잡고 항상 같은 방향으로 그 손을 움직이면 가장 좋습니다.
위한 이동의 마지막 번호 n
디스크는 2^n - 1
(가) move n disc to destination
과정을 통해 반이다.
마지막으로, 동료, 아내 / 남편 또는 심지어 개 (심지어 듣지 않는 경우에도)에게 문제를 설명 하는 것이 어떻게 깨달음을 굳힐 수 있는지는 재밌 습니다.
이 모든 설명을 읽은 후 교수님이 하노이의 탑 재귀 솔루션을 설명하는 데 사용한 방법을 고려할 것이라고 생각했습니다. n 은 링 수를 나타내고 A, B, C는 못을 나타내는 알고리즘 입니다. 함수의 첫 번째 매개 변수는 링 수, 두 번째 매개 변수는 소스 페그, 세 번째 매개 변수는 대상 페그, 네 번째 매개 변수는 예비 페그입니다.
procedure Hanoi(n, A, B, C);
if n == 1
move ring n from peg A to peg B
else
Hanoi(n-1, A, C, B);
move ring n-1 from A to C
Hanoi(n-1, C, B, A);
end;
저는 대학원에서 작게 생각하는 것이 결코 부끄러워하지 않도록 배웠습니다. 따라서 n = 5에 대한이 알고리즘을 살펴 보겠습니다. 먼저 자신에게 물어볼 질문 은 5 번째 고리를 A에서 B로 옮기고 싶은지 여부입니다. 다른 4 개의 고리는 어디에 있습니까? 다섯 번째 링이 페그 A를 차지하고이를 페그 B로 이동하려는 경우 다른 4 개의 링은 페그 C에만있을 수 있습니다. 하노이 함수 위의 알고리즘에서 (n-1, A, C, B)다른 고리 4 개를 모두 C로 이동하려고합니다. 따라서 고리 5는 A에서 B로 이동할 수 있습니다.이 알고리즘에 따라 n = 4를 살펴 봅니다. 고리 4가 A에서 C로 이동하면 반지 3 개 이하? 그들은 페그 B에만있을 수 있습니다. 다음으로, n = 3 인 경우, 링 3이 A에서 B로 이동하면 링 2와 1은 어디에 있습니까? 물론 페그 C에서. 이 패턴을 계속 따르면 재귀 알고리즘이 수행하는 작업을 시각화 할 수 있습니다. 이 접근 방식은 마지막 디스크를 먼저보고 첫 번째 디스크를 마지막으로 본다는 점에서 초보자의 접근 방식과 다릅니다.
디스크 직경이 정수 (4,3,2,1)로 표시되는 스택으로 생각하십시오. 첫 번째 재귀 호출은 3 번 호출되므로 다음과 같이 런타임 스택을 채 웁니다.
- 첫 번째 호출 : 1. 두 번째 호출 : 2,1. 세 번째 호출 : 3,2,1.
첫 번째 재귀가 끝나면 런타임 스택의 내용이 가장 큰 지름에서 가장 작은 것 (선입 선출)까지 중간 극으로 팝됩니다. 다음으로 직경이 4 인 디스크가 대상으로 이동됩니다.
두 번째 재귀 호출은 요소를 중간 극에서 대상으로 이동하는 것을 제외하고 첫 번째 재귀 호출과 동일합니다.
첫 번째 재귀 호출은 dest를 보조 파일로 사용하여 소스에서 가장 큰 조각을 제외한 모든 조각을 이동합니다. 완료되면 가장 큰 조각을 제외한 모든 조각이 누워 있고 가장 큰 조각은 무료입니다. 이제 가장 큰 것을 dest로 이동하고 다른 재귀 호출을 사용하여 모든 조각을 dest로 이동할 수 있습니다.
재귀 호출은 가장 큰 조각에 대해 아무것도 알지 못하지만 (즉, 무시합니다), 재귀 호출은 더 작은 조각 만 처리하므로 가장 큰 조각으로 자유롭게 이동하거나 이동할 수 있기 때문에 괜찮습니다.
간단 해. A에서 C로 이동한다고 가정합니다.
디스크가 하나뿐이면 이동하십시오.
디스크가 두 개 이상인 경우
- A에서 B로 아래쪽 디스크를 제외한 모든 디스크 (n-1 개 디스크) 이동
- 하단 디스크를 A에서 C로 이동
- n-1 디스크를 첫 번째 단계에서 A에서 C로 이동
n-1 디스크를 이동할 때 n 번째 디스크는 전혀 문제가되지 않습니다 (다른 모든 디스크보다 커지면).
n-1 디스크를 이동하는 것은 n-1 = 1이 될 때까지 같은 문제에서 다시 반복됩니다.이 경우 첫 번째 if (이동해야하는 위치)가됩니다.
질문에 대한 대답은 프로그램이 "src"에서 "aux"로, 홀수는 "src"에서 "dst"까지라는 것을 어떻게 알 수 있는지 프로그램에 있습니다. 4 개의 디스크로 주먹 동작을 분해하면 다음과 같습니다.
hanoi(4, "src", "aux", "dst");
if (disc > 0) {
hanoi(3, 'src', 'dst', 'aux');
if (disc > 0) {
hanoi(2, 'src', 'aux', 'dst');
if (disc > 0) {
hanoi(1, 'src', 'dst', 'aux');
if (disc > 0) {
hanoi(0, 'src', 'aux', 'dst');
END
document.writeln("Move disc" + 1 + "from" + Src + "to" + Aux);
hanoi(0, 'aux', 'src', 'dst');
END
}
또한 4 개의 디스크 (짝수)를 사용한 첫 번째 동작은 Src에서 Aux로 이동합니다.
일부 친구들이 제안했듯이 이전 두 가지 답변을 제거하고 여기에 통합했습니다.
이것은 당신에게 명확한 이해를 제공합니다.
일반적인 알고리즘이란 ....
연산:
solve(n,s,i,d) //solve n discs from s to d, s-source i-intermediate d-destination
{
if(n==0)return;
solve(n-1,s,d,i); // solve n-1 discs from s to i Note:recursive call, not just move
move from s to d; // after moving n-1 discs from s to d, a left disc in s is moved to d
solve(n-1,i,s,d); // we have left n-1 disc in 'i', so bringing it to from i to d (recursive call)
}
public static void hanoi(int number, String source, String aux, String dest)
{
if (number == 1)
{
System.out.println(source + " - > "+dest);
}
else{
hanoi(number -1, source, dest, aux);
hanoi(1, source, aux, dest);
hanoi(number -1, aux, source, dest);
}
}
void TOH(int n, int a, int b){
/*Assuming a as source stack numbered as 1, b as spare stack numbered as 2 and c as target stack numbered as 3. So once we know values of a and b, we can determine c as there sum is a constant number (3+2+1=)6.
*/
int c = 6-a-b;
if(n==1){
cout<<"Move from "<<a<<" to "<<b<<"\n";
}
else{
// Move n-1 disks from 1st to 2nd stack. As we are not allowed to move more than one disks at a time, we do it by recursion. Breaking the problem into a simpler problem.
TOH(n-1, a, c);
// Move the last alone disk from 1st to 3rd stack.
TOH(1, a, b);
// Put n-1 disks from 2nd to 3rd stack. As we are not allowed to move more than one disks at a time, we do it by recursion. Breaking the problem into a simpler problem.
TOH(n-1, c, b);
}
}
int main() {
TOH(2, 1, 3);
cout<<"FINISHED \n";
TOH(3, 1, 3);
cout<<"FINISHED \n";
TOH(4, 1, 3);
return 0;
}
여기에 설명이 있습니다. 사진 좀 봐->
를 호출 Movetower(3,a,b,c)
하면 3 개의 디스크를 모두 타워에서 타워 A
로 이동하려고합니다 B
. 따라서 순차 호출은->
1. Movetower(3,a,b,c) // No Move needed
2. Movetower(2,a,c,b) // No move needed
3. Movetower(1,a,b,c) // Here is the time to move, move disc1 from a to b
4. Movetower(2,a,c,b) // Returning to this call again, this is the time to move disc2 from a to c
5. Movetower(1,b,c,a) // Again the time to move, this time disc1 from b to c
6. Movetower(3,a,b,c) // Returning to this call again, this is the time to move disc3 from a to b
7. Movetower(2,c,b,a) // Not the time to move
8. Movetower(1,c,a,b) // Here is the time to move, move disc1 from c to a
9. Movetower(2,c,b,a) // Returning to this call again, this is the time to move disc2 from c to b
10.Movetower(1,c,a,b) // Here is the time to move, move disc1 from a to b
도움이되기를 바랍니다 :)
애니메이션 : https://www.cs.cmu.edu/~cburch/survey/recurse/hanoiex.html
소스 타워, 대상 타워 및 도우미 타워의 세 개의 타워가 있습니다. 소스 타워에는 모든 디스크가 있으며 대상은 모든 디스크를 대상 타워로 이동하고 그렇게함으로써 더 큰 디스크를 더 작은 디스크 위에 놓지 않도록하는 것입니다. 아래 단계에서 재귀를 사용하여이 문제를 해결할 수 있습니다.
우리는이 N 소스 타워 디스크의 번호를
기본 사례 : n = 1 소스 타워에 디스크가 하나만있는 경우 대상 타워로 이동합니다.
재귀 사례 : n> 1
- 소스 타워에서 헬퍼 타워로 상위 n-1 디스크 이동
- 나머지 n 번째 디스크 (1 단계 이후)를 대상 타워로 이동
- 현재 헬퍼 타워에있는 n-1 디스크
를 소스 타워를 도우미로 사용하여 대상 타워로 이동합니다.
자바 소스 코드 :
private void towersOfHanoi(int n, char source, char destination, char helper) {
//Base case, If there is only one disk move it direct from source to destination
if(n==1){
System.out.println("Move from "+source+" to "+destination);
}
else{
//Step1: Move the top n-1 disks from source to helper
towersOfHanoi(n-1, source, helper, destination);
//Step2: Move the nth disk from source to destination
System.out.println("Move from "+source+" to "+destination);
/*Step3: Move the n-1 disks(those you moved from source to helper in step1)
* from helper to destination, using source(empty after step2) as helper
*/
towersOfHanoi(n-1, helper, destination, source);
}
}
CS 학생으로서 수학 입문에 대해 들어 보셨을 것입니다. 하노이 타워의 재귀 솔루션은 유사하게 작동합니다. 단지 다른 부분은 B와 C로 완전히 잃어 버리지 않는 것입니다.
간단한 의미에서 아이디어는 절차 중에 언제든지 작은 디스크와 겹치는 큰 디스크없이 현재와 동일한 순서의 디스크로 정의 된 세 개의 타워 중 다른 타워를 채우는 것입니다.
'A', 'B'및 'C'를 세 개의 타워로 지정합니다. 'A'는 처음에 'n'디스크를 포함하는 타워입니다. 'B'는 중간 타워로 사용할 수 있으며 'C'는 대상 타워로 사용할 수 있습니다.
알고리즘은 다음과 같습니다.
- 'C'를 사용하여 타워 'A'에서 'B'로 n-1 디스크 이동
- 'A'에서 'C'로 디스크 이동
- 'A'를 사용하여 타워 'B'에서 'C'로 n-1 디스크 이동
코드는 Java에서 다음과 같습니다.
public class TowerOfHanoi {
public void TOH(int n, int A , int B , int C){
if (n>0){
TOH(n-1,A,C,B);
System.out.println("Move a disk from tower "+A +" to tower " + C);
TOH(n-1,B,A,C);
}
}
public static void main(String[] args) {
new TowerOfHanoi().TOH(3, 1, 2, 3);
}
}
다음은 golang과 함께 재귀를 사용하는 하노이 타워 문제에 대한 솔루션 코드입니다. `패키지 메인
import "fmt"
func main() {
toi(4, "src", "dest", "swap")
}
func toi(n int, from, to, swap string) {
if n == 0 {
return
}
if n == 1 {
fmt.Printf("mov %v %v -> %v\n", n, from, to)
return
}
toi(n-1, from, swap, to)
fmt.Printf("mov %v %v -> %v\n", n, from, to)
toi(n-1, swap, to, from)
}`
이 python3 예제는 재귀 솔루션을 사용합니다.
# Hanoi towers puzzle
# for each n, you have to move n-1 disks off the n disk onto another peg
# then you move the n disk to a free peg
# then you move the n-1 disks on the other peg back onto the n disk
def hanoi(n):
if n == 1:
return 1
else:
return hanoi(n-1) + 1 + hanoi(n-1)
for i in range(1, 11):
print(f"n={i}, moves={hanoi(i)}")
산출:
n=1, moves=1
n=2, moves=3
n=3, moves=7
n=4, moves=15
n=5, moves=31
n=6, moves=63
n=7, moves=127
n=8, moves=255
n=9, moves=511
n=10, moves=1023
그러나 물론 얼마나 많은 움직임을 계산하는 가장 효율적인 방법은 대답이 항상 2 ^ n보다 1 작다는 것을 깨닫는 것입니다. 따라서 수학적 해는 2 ^ n-1입니다.
오늘이 비디오를 보셨습니다 : Recursion 'Super Power'(in Python)-컴퓨터 애호가 와 저는 Thorsten Altenkirch 교수의 코드 가 매우 아름답고 우아한 재귀 코드이며 항상 품질이있는 것은 아닙니다. 답변에 표시 할 비디오.
def move(f,t) :
print("move disc from {} to {}!".format(f,t))
def hanoi(n,f,h,t) :
if n==0 :
pass
else :
hanoi(n-1,f,t,h)
move(f,t)
hanoi(n-1,h,f,t)
우리의 hanoi
기능은 4 개 매개 변수가 있습니다 :
n
: 디스크 수f
: 디스크가있는 출처 (원본 )h
: 중간 단계 '경유' (도우미)t
: 디스크가 끝날 최종 위치 (타겟)
>>> hanoi(4,"A","B","C")
move disc from A to B!
move disc from A to C!
move disc from B to C!
move disc from A to B!
move disc from C to A!
move disc from C to B!
move disc from A to B!
move disc from A to C!
move disc from B to C!
move disc from B to A!
move disc from C to A!
move disc from B to C!
move disc from A to B!
move disc from A to C!
move disc from B to C!
Tower (N,source,aux.dest):
if N =1 Then Write : Source -> dest return end of if
N-1 디스크를 페그 소스에서 페그 Aux로 이동
call Tower (N-1, source, dest, aux)
- 쓰기 소스-> 대상
N-1 디스크를 peg aux에서 peg dest로 이동
call Tower (N-1, source, dest, aux)
- 반환
/ ** * * / 패키지 com.test.recursion;
/** * @author kamals1986 The Recursive algorithm for Tower of Hanoi Problem The * algorithm grows by power(2,n). */ public class TowerOfHanoi {
private static String SOURCE_PEG = "B";
private static String SPARE_PEG = "C";
private static String TARGET_PEG = "A";
public void listSteps(int n, String source, String target, String spare) {
if (n == 1) {
System.out.println("Please move from Peg " + source + "\tTo Peg\t"
+ target);
} else {
listSteps(n - 1, source, spare, target);
listSteps(1, source, target, spare);
listSteps(n - 1, spare, target, source);
}
}
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
new TowerOfHanoi().listSteps(18, SOURCE_PEG, TARGET_PEG, SPARE_PEG);
long endTime = System.currentTimeMillis();
System.out.println("Done in " + (endTime - startTime) / 1000
+ "\t seconds");
}
}
def Hanoi(n, A, B, C):
if(n==1): print "move plates to empty peg"
else:
Hanoi(n-1, A, B, C)
print "move"+str(n)+" to peg "+C
Hanoi(n-1, B, C, A)
I am trying to get recursion too.
I found a way i think,
i think of it like a chain of steps(the step isnt constant it may change depending on the previous node)
I have to figure out 2 things:
- previous node
- step kind
- after the step what else before call(this is the argument for the next call
example
factorial
1,2,6,24,120 ......... or
1,2*(1),3*(2*1),4*(3*2*1,5*(4*3*2*1)
step=multiple by last node
after the step what i need to get to the next node,abstract 1
ok
function =
n*f(n-1)
its 2 steps process
from a-->to step--->b
i hoped this help,just think about 2 thniks,not how to get from node to node,but node-->step-->node
node-->step is the body of the function step-->node is the arguments of the other function
bye:) hope i helped
참고 URL : https://stackoverflow.com/questions/1223305/tower-of-hanoi-recursive-algorithm
'code' 카테고리의 다른 글
Docker Compose-여러 컨테이너간에 명명 된 볼륨 공유 (0) | 2020.11.24 |
---|---|
두 숫자의 해시 코드 만들기 (0) | 2020.11.24 |
C와 Python-모듈로 (%) 연산의 다른 동작 (0) | 2020.11.24 |
내부 블록 수준 요소 중첩 (0) | 2020.11.24 |
다른보기 내에서보기를 호출 할 수 있습니까? (0) | 2020.11.24 |