ACM之递归组合【递归很重要 】

ACM之递归组合【递归很重要 】
ACM之递归组合【递归很重要 】

递归求解几类排列组合问题

西南交通大学吴汉舟2009年

Welcome to JudgeOnline

对于搜索的深度很深或深度不固定的情况,则无法用枚举的方法来设置循环嵌套的层数,这时可以考虑用递归法来完成搜索任务。递归是一种常用算法,它是搜索的另一种实现方式。如果在算法设计中采用一个函数或过程直接或间接地调用它自身来解决问题的方法,则称该方法为递归算法。递归算法必须要设计好一个或若干个确定的递归终止条件。

一、类循环组合排列

Sample Input:

4 2

Sample Output

0000

0001

0010

0011

0100

0101

0110

0111

1000

1001

1010

1011

1100

1101

1110

1111

//Program

#include

int n,m;

int mat[10];

void solve(int l){

if(l>=n){

for(int i=0;i

puts("");

return;

}

for(int i=0;i

mat[l]=i;

solve(l+1);

}

}

int main(){

while(scanf("%d%d", &n, &m)!=EOF){

solve(0);

}

return 0;

}

二、全组合排列

Sample Input

3

1 2 3

Sample Output

123

132

213

231

312

321

//Program

#include

#include

const int maxn=11;

int n;

int used[maxn];//标记数组

int mat[maxn];//存储数组

int num[maxn];//输出数组

void solve(int l){

if(l>=n){

for(int i=0;i

puts("");

return;

}

for(int i=0;i

if(!used[i]){

used[i]=1;

num[l]=mat[i];

solve(l+1);

used[i]=0;

}

}

}

int main(){

while(scanf("%d", &n)!=EOF){

for(int i=0;i

memset(used,0,sizeof(used));

solve(0);

}

return 0;

}

三、非重复组合排列(含重复数字时,生成不重复组合排列)Sample Input

4

1 2 2 3

Sample Output

1223

1232

1322

2123

2132

2213

2231

2312

2321

3122

3212

3221

//Program

#include

const int maxn=10;

int n,var;

int Index;

int used[maxn],mat[maxn],num[maxn];

void push(int varNum){ //压栈

for(int i=0;i

if(mat[i]==varNum){

++used[i];

return;

}

}

mat[Index]=varNum;

++used[Index++];

}

void solve(int l){ //求解

if(l>=n){

for(int i=0;i

puts("");

return;

}

for(int i=0;i

if(used[i]){

used[i]--;

num[l]=mat[i];

solve(l+1);

used[i]++;

}

}

}

int main(){

while(scanf("%d", &n)!=EOF){

Index=0;

for(int i=0;i

scanf("%d", &var);

push(var);

}

solve(0);

}

return 0;

}

四、普通选择性组合排列Sample Input

5 3

1 2 3 4 5

Sample Output

123

124

125

134

135

145

234

235

245

345

//Program

#include

const int maxn=10;

int totalN,selectM;

int mat[maxn];//存储数组

int num[maxn];//输出数组

void solve(int startVar,int selectVar){ if(selectVar>=selectM){

puts("");

return;

}

for(int i=startVar;i

num[selectVar]=mat[i];

solve(i+1,selectVar+1);

}

}

int main(){

while(scanf("%d%d", &totalN, &selectM)!=EOF){ for(int i=0;i

solve(0,0);

}

return 0;

}

五、生成全子集组合排列(不含空集)

Sample Input

4

1 2 3 4

Sample Output

1

12

123

1234

124

13

134

14

2

23

234

24

3

34

4

//Program

#include

const int maxn=10;

int n;

int mat[maxn];

int num[maxn];

void solve(int cur_totalVar,int nextVar){

if(cur_totalVar)puts("");

for(int i=nextVar;i

num[cur_totalVar]=mat[i];

solve(cur_totalVar+1,i+1);

}

}

int main(){

while(scanf("%d", &n)!=EOF){

for(int i=0;i

solve(0,0);

}

return 0;

}

//注意:倘若需要输出空集(也即输出一个换行),可做如下修改

//在函数solve()中,将if(cur_totalVar)puts(""); 改为puts("");

六、非重复生成全子集组合排列(含重复数字时,生成不重复全子集组合排列)Sample Input

4

1 2 2 3

Sample Output

1

12

122

1223

123

13

2

22

223

23

3

//Program

#include

const int maxn=10;

int n,var;

int Index;

int used[maxn],mat[maxn],num[maxn];

void push(int varNum){ //压栈

for(int i=0;i

if(mat[i]==varNum){

++used[i];

return;

}

}

mat[Index]=varNum;

++used[Index++];

}

void solve(int l,int p){ //求解

for(int i=0;i

if(l)puts("");

for(int i=p;i

if(used[i]){

used[i]--;

num[l]=mat[i];

solve(l+1,i);

used[i]++;

}

}

}

int main(){

while(scanf("%d", &n)!=EOF){

Index=0;

for(int i=0;i

scanf("%d", &var);

push(var);

}

solve(0,0);

}

return 0;

}

//注意:倘若需要输出空集(也即输出一个换行),可做如下修改

//在函数solve()中,将if(l)puts(""); 改为puts("");

总结:递归思想在搜索技术中有着广泛的应用,应当熟练掌握和学习这种思想,对求解这一类搜索题目大有裨益。

相关主题
相关文档
最新文档