排列组合中的搜索

来源:互联网 发布:来源百度地图大数据 编辑:程序博客网 时间:2024/06/05 09:18

本质是都是树的深搜,只不过是递归的出口条件,输出形式以及递归过程的条件不一样。

1:全排列问题:

输入:3

           1 2 4       

 输出:

1 2 4

1 4 2

2 1 4

2 4 1

4 1 2

4 2 1

参考代码实现:

#include<iostream>#include<stdio.h>using namespace std;#define  maxn 15int n;int num[maxn];//输入n个数int used[maxn];//标记num[i]是否使用过int rcd[maxn];//标记每个位置的数void  fullSort(int k)//全排列函数{   if(k==n)   {     for(int i=0;i<n;i++)     {       printf("%d",rcd[i]);       if(i<n-1)printf(" ");     }     printf("\n");     return;   }   else    {      for(int j=0;j<n;j++)//枚举所有的数      {         if(!used[j])//若num[i]没有使用过,则标记为已用         {            used[j]=1;            rcd[k]=num[j];//在k的位置上放上该数            fullSort(k+1);//填写写一个位置            used[j]=0;//回溯,清零标记         }      }    }}int  read_data(){    int i;    if(scanf("%d",&n)==EOF) return 0;    for(i=0;i<n;i++)scanf("%d",&num[i]);    for(i=0;i<n;i++) used[i]=0;    return 1;}int main(){    while(read_data())fullSort(0);//从第一位置开始    return 0;}


2:一般组合问题:

输入:4 3

         1 2  3 4

输出:1 2 3

           1 2 4

           1 3 4

           2 3 4

参考代码实现:

/*选择组合排列 C(4,3)*/#include<iostream>#include<fstream>using namespace std;#define maxn 15int n,m;int rcd[maxn];int num[maxn];void  select_Combination(int k,int p){    if(k==m)    {       for(int i=0;i<m;i++)//只要填满m个位置就要输出       {         printf("%d",rcd[i]);         if(i<m-1) printf(" ");       }        printf("\n");        return;    }    else    {      for(int j=p;j<n;j++)//无序,上一次位置是num[p-1],所以这一次位置从num[p],试探填充。不需要标记有没有用过。      {         rcd[k]=num[j];         select_Combination(k+1,j+1);//填下一个位置。      }    }}int  read_data(){    if(scanf("%d%d",&n,&m)==EOF) return 0;    for(int i=0;i<n;i++)scanf("%d",&num[i]);    return 1;}int main(){    while(read_data())select_Combination(0,0);    return 0;}

3:n个数的集合问题(2的n次方-1个情况)

输入: 3

          1 2 3

输出:1

          1 2

          1 2 3

          1 3

          2

          2 3

          3

参考代码实现:

 

/*求n个数所有集合 */#include<iostream>#include<stdio.h>#include<time.h>using namespace std;#define maxn 15int n;int rcd[maxn];int num[maxn];void full_Combination(int k,int p){   int i;   for(i=0;i<k;i++)//每次进入递归函数都输出。   {     printf("%d",rcd[i]);     if(i<k-1) printf(" ");   }   if(k)printf("\n");   for(i=p;i<n;i++)//循环从p开始,结束条件i>=n;   {      rcd[k]=num[i];//填写该位置的数。      full_Combination(k+1,i+1);//下个位置    }}int  read_data(){    if(scanf("%d",&n)==EOF) return 0;    for(int i=0;i<n;i++)scanf("%d",&num[i]);    return 1;}int main(){    //int start,end;    //start=clock();    while(read_data())full_Combination(0,0);    //end=clock();    //cout<<(double)(end-start)/CLOCKS_PER_SEC<<endl;    return 0;}

4:不重复排列

输入:3

          1 1 2

 输出:1 1 2

            1 2 1

            2 1 1

思路:如果像第一种那样,就会多出1 1 2 ,2  1 1,1 2 1的重复,思想是记录本质不同的数出现的次数,输入的过程要过滤重复的元素。把循环的长度减少到不同元素的个数。

参考代码实现:

#include<iostream>#include<stdio.h>using namespace std;#define maxn 10int n,m;int rcd[maxn];int used[maxn];int num[maxn];void norepeat_Sort(int k){    if(k==n)    {       for(int i=0;i<n;i++)       {          printf("%d",rcd[i]);          if(i<n-1)printf(" ");       }     printf("\n");     return;    }    else    {      for(int j=0;j<m;j++)//枚举不同元素的个数      {       if(used[j]>0)//若num[i]还没用完,继续用这个数填充下个位置。       {        used[j]--;//可用次数减少        rcd[k]=num[j];        norepeat_Sort(k+1);//填写下个位置        used[j]++;//可用次数还原       }      }    }}int read_data(){    int i,j,val;    if(scanf("%d",&n)==EOF)return 0;    m=0;    for(i=0;i<n;i++)    {        scanf("%d",&val);        for(j=0;j<m;j++)//删选不同的元素,并记录每一元素记录的次数。        {          if(num[j]==val)          {            used[j]++;            break;          }        }        if(j==m)        {         num[m]=val;         used[m++]=1;        }    } return 1;}int main(){    while(read_data())norepeat_Sort(0);    return 0;}

5:不重复的组合

输入:3

         1 1 3

输出:1

          1 1

          1 1 3

          1 3

          3

思路:同上(本质一样)

参考代码实现:

#include<iostream>#include<stdio.h>using namespace std;#define maxn 10int n,m;int rcd[maxn];int used[maxn];int num[maxn];void norepeat_Comb(int k,int p){    for(int i=0;i<k;i++)//每次都输出       {          printf("%d",rcd[i]);          if(i<k-1)printf(" ");       }     if(k)printf("\n");     for(int j=p;j<m;j++)//从P开始,枚举不同元素的个数      {       if(used[j]>0)//若num[i]还没用完,继续用这个数填充下个位置。       {        used[j]--;//可用次数减少        rcd[k]=num[j];        norepeat_Comb(k+1,j);//这里从j开始,不是j+1;因为不止一个数、        used[j]++;//可用次数还原       }      }}int read_data(){    int i,j,val;    if(scanf("%d",&n)==EOF)return 0;    m=0;    for(i=0;i<n;i++)    {        scanf("%d",&val);        for(j=0;j<m;j++)//删选不同的元素,并记录每一元素记录的次数。        {          if(num[j]==val)          {            used[j]++;            break;          }        }        if(j==m)        {         num[m]=val;         used[m++]=1;        }    } return 1;}int main(){    while(read_data())norepeat_Comb(0,0);    return 0;}


 

 


 

           

 

 

 

原创粉丝点击