* 所谓回溯:就是搜索一棵状态树的过程,这个过程类似于图的深度优先
* 搜索(DFS),在搜索的每一步(这里的每一步对应搜索树的第i层)中
* 产生一个正确的解,然后在以后的每一步搜索过程中,都检查其前一步
* 的记录,并且它将有条件的选择以后的每一个搜索状态(即第i+1层的
* 状态节点)。
/*
* 回溯法 实现 排列组合
*
* 所谓回溯:就是搜索一棵状态树的过程,这个过程类似于图的深度优先
* 搜索(DFS),在搜索的每一步(这里的每一步对应搜索树的第i层)中
* 产生一个正确的解,然后在以后的每一步搜索过程中,都检查其前一步
* 的记录,并且它将有条件的选择以后的每一个搜索状态(即第i+1层的
* 状态节点)。
*
* 需掌握的基本算法:
* 排列:就是从n个元素中同时取r个元素的排列,记做P(n,r)。(当r=n时,
* 我们称P(n,n)=n!为全排列) 例如我们有集合OR = {1,2,3,4},那么
* n = |OR| = 4, 且规定r=3, 那么P(4,3)就是:
*
* {1,2,3}; {1,2,4}; {1,3,2}; {1,3,4}; {1,4,2}; {1,4,3};
* {2,1,3}; {2,1,4}; {2,3,1}; {2,3,4}; {2,4,1}; {2,4,3};
* {3,1,2}; {3,1,4}; {3,2,1}; {3,2,4}; {3,4,1}; {3,4,2};
* {4,1,2}; {4,1,3}; {4,2,1}; {4,2,3}; {4,3,1}; {4,3,2}
*
*/
#include
#ifndef MAXN
#define MAXN 5
#endif
static int n = 3, r = 3; /* P(n,r) */
static char used[MAXN]; /* 待排列数据使用标记 */
static char p[MAXN]; /* 解空间 - 保存每次形成的排列结果 */
static char data[] = {'a','b','c'}; /* 待排列组合的数据空间 */
/*
* permute(pos -- 表示在解空间中填写数据的下标位置)
* {
* 如果解空间填写满了 打印解空间当前的排列结果 函数返回
*
* for (i=0; i
* {
* 尝试在这个下标位置填写每一个待排列的数据
* (但这些数据可填写的前提是数据没有被标记为已使用)
*
* 填写后, 把这个下标为i的数据标记为已使用
*
* permute(pos+1); -- 填写解空间中下一个位置
*
* 下标为i的数据已参与了解空间下标pos处的排列
* 取消已使用标记(因为该数据可以在解空间其他下标处使用)
* 继续for循环考察下一个待排列数据
* }
* }
*
* used[i] == 1 - 待排列空间中下标i处的数据已被使用;
* used[i] == 0 - 可以使用待排列空间中下标i处的数据;
*/
void permute(int pos)
{
int i = 0;
if (pos == r)
{
for (i=0; i
printf("%c, ",p[i]);
printf(" ");
return;
}
for (i=0; i
{
if (!used[i])
{
used[i]++;
p[pos] = data[i];
permute(pos+1);
used[i]--;
}
}
}
void main() { permute(0); }