源博文地址:http://blog.csdn.net/wumuzi520/article/details/8087501
字母a-z,数字0-9,现需要其中任意3个作为密码,请输出所有可能组合。首先,看到这问题的时候我们就会想到动态规划。先给出比较简单的例子,就是给定1,2,3,4,5个数字,选出3个数字进行打印。从后往前分析:
先分两种情况,如果选择5,那么剩下的两个可以从1,2,3,4中选择两个出来,如果第二个数字选择4,那么从1,23中选择第三个数字出来,如果不选择4,则冲1,2,3中选择两个出来.....,;如果不选择5,那么就要从1,2,3,4中选择3个出来......这就是其基本思想。首先可以用递归解决这个问题,但是要找到递归结束的条件。程序中会给予标注。
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
void combination_cursion(int *a,int len,int m,int *out,int out_len)
{
int i;
if(m==0)//out中已经存储了m个数字
{
for(i=0;i<out_len;i++)
printf("%d\t",out[i]);
printf("\n");
return ;
}
for(i=len;i>=m;i--)//从前向后依次选定一个,动态规划的体现
{
out[m-1]=a[i-1];//选定一个之后
combination_cursion(a,i-1,m-1,out,out_len);//从前i-1个后选m-1,递归
}
}
void print_combination_cursion(int *a,int n,int m)
{
assert(a!=NULL);
assert(n>=m);
int *out=(int*)malloc(sizeof(int)*m);
combination_cursion(a,n,m,out,m);
}
int main()
{
int array[] = {1,2,3,4,5};
print_combination_cursion(array,sizeof(array)/sizeof(int),3);
}
另外一个方法,就是二进制组合算法:
假设从n个数中选取m个进行打印。开辟一个n长度的数组,首先设定前m个位1,其后的都为0。当存储的值为1的时候表示北选中,当存储的值为0的时候表示没有选中。然后从左到右进行扫描,找到第一个“10”的组合,并把其调整为“01”组合,之后把这个调整的“01”组合之前的所有的1移动到最左端(这点与原文有出入),注意,只有第一位即索引值为0的那位为0的时候才需要移动,其他情况不需要移动。
当第一个“1”移动到数组的m-n的位置,即n个“1”全部移动到最右端时,就得到了最后一个组合。
例如求5中选3的组合:
1 1 1 0 0 //1,2,3
1 1 0 1 0 //1,2,4
1 0 1 1 0 //1,3,4
0 1 1 1 0 //2,3,4
1 1 0 0 1 //1,2,5
1 0 1 0 1 //1,3,5
0 1 1 0 1 //2,3,5
1 0 0 1 1 //1,4,5
0 1 0 1 1 //2,4,5
0 0 1 1 1 //3,4,5
接下来给出程序:
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<windows.h>
void swap(int *a,int *b)
{
int temp=*a;
*a=*b;
*b=temp;
}
void combination(int *a,int n,int m)
{
assert(n>=m);
assert(a!=NULL);
int is_find;
int i,j,k;
int *p_table=(int*)malloc(sizeof(int)*n);
memset(p_table,0,sizeof(int)*n);
for(i=0;i<m;i++)
p_table[i]=1;
is_find=0;
do
{
for(i=0;i<n;i++)
{
if(p_table[i]==1)
printf("%d\t",a[i]);
}
printf("\n");
is_find=0;
for(i=0;i<n-1;i++)
{
if(p_table[i]==1&&p_table[i+1]==0)//找到"10"
{
swap(&p_table[i],&p_table[i+1]);//换成"01"
is_find=1;
if(p_table[0]==0)
{
for(k=0,j=0;k<i;k++)//将交换后"01"之前的1移动到最左端
{
if(p_table[k])
{
swap(&p_table[k],&p_table[j]);
j++;
}
}
}
break;
}
}
}while(is_find);
}
int main()
{
int array[] = {1,2,3,4,5};
combination(array,sizeof(array)/sizeof(int),3);
}