如何使用回溯打印所有排列?
Posted
技术标签:
【中文标题】如何使用回溯打印所有排列?【英文标题】:How to print all permutation using backtracking? 【发布时间】:2021-03-25 12:19:56 【问题描述】:此代码打印 N-1 个项目的所有排列。但我无法理解一件事: 当 n=N 时,它返回调用它的位置并使 flag[n-1] = false。因此,i = N-1 并打破循环。但是当 n=N-2 到 0 时,其余的排列如何打印或返回?
void perm(int n)
if (n == N)
for (int i = 0; i < N ; i++)
cout<<a[i]<<" ";
cout<<endl;
return;
for (int i = 0; i < N; i++)
if (flag[i]) continue;
a[n] = i;
flag[i] = true;
cout<<i<<endl;
perm(n + 1);
cout<<i<<endl;
flag[i] = false;
【问题讨论】:
这是一个使用调试器的好机会 您能解释一下您的代码中的N
、flag
和a
是什么吗?
N
是排列长度,flag
是给定数字是否已被使用,a
是给定位置的选定数字。
您的问题是 “” 问题中的代码是 “打印 N-1 项的所有排列”。 你的实际问题是什么?
【参考方案1】:
您需要考虑到函数调用最终是嵌套的。
下面的每个缩进显示一个嵌套调用:
main()
entering perm(0)
entering perm(1)
i = 0
entering perm(2)
let's say N is 2, this will print and return
now perm(1) continues
i becomes 1
entering perm(2)
...
由于return
仅从当前函数调用返回,而不是所有函数调用,排列继续打印。
为了熟悉这个,试试这个:
void perm(int n)
std::cout << "Entering perm " << n << std::endl;
if (n == N)
for (int i = 0; i < N ; i++)
cout<<a[i]<<" ";
cout<<endl;
std::cout << "Exiting perm " << n << std::endl;
return;
for (int i = 0; i < N; i++)
if (flag[i]) continue;
a[n] = i;
flag[i] = true;
cout<<i<<endl;
std::cout << "about to call perm" << std::endl;
perm(n + 1);
std::cout << "finished call to perm" << std::endl;
cout<<i<<endl;
flag[i] = false;
std::cout << "Exiting perm " << n << " (2)"<< std::endl;
【讨论】:
当调用 perm(2) ,i=1 时,它返回并使 flag[1] = false。因此,它打破了循环,并且没有其他返回关键字。但是 perm(1) 如何继续?打破循环后,它会自行进入 perm(1) 吗?我错过了吗? 是的,在调试器中试试。您似乎还不熟悉嵌套函数调用。请记住,如果perm
调用自身,它将在返回时继续原处。 i
也会有多个值,每个嵌套级别一个
非常感谢!以上是关于如何使用回溯打印所有排列?的主要内容,如果未能解决你的问题,请参考以下文章