组合数 【nyoj-32】【stl】【dfs】

来源:互联网 发布:js 截取字符串后几位 编辑:程序博客网 时间:2024/05/18 04:56

组合数

时间限制:3000 ms  |  内存限制:65535 KB
难度:3
描述
找出从自然数1、2、... 、n(0<n<10)中任取r(0<r<=n)个数的所有组合。
输入
输入n、r。
输出
按特定顺序输出所有组合。
特定顺序:每一个组合中的值从大到小排列,组合之间按逆字典序排列。
样例输入
5 3
样例输出
543542541532531521432431421321

题解:此题有两种解题方法<1>利用stl中的prev_permutation()函数。<2>使用dfs。


代码如下:

<1> 利用prev_permutation()函数      (降序全排列)。

#include<cstdio>#include<algorithm>using namespace std;int a[15];   //存储数据int b[15];   //比对是否是降序排列int c[15];   //比对是否与上次输出数列一样int n,r;bool cmp(int x,int y){  //由大到小排序 return x>y;}bool Judge(){     //判断是否是降序 int num=0;sort(b,b+r,cmp);for(int i=0;i<r;i++){if(a[i]==b[i]) num++;}return num==r;}bool Judge2(){    //判断本次数列是否与上次输出数列重复int num2=0;for(int i=0;i<r;i++){if(c[i]==a[i]) num2++;}if(num2!=r) return true;return false;}int main(){scanf("%d%d",&n,&r);for(int i=0;i<n;i++)  //赋值 a[i]=i+1;sort(a,a+n,cmp);  //首次降序排列 do{for(int i=0;i<r;i++)b[i]=a[i];if(Judge()&&Judge2()){    //判断,若是降序且与先前输出数列不重复for(int i=0;i<r;i++){c[i]=a[i];}for(int i=0;i<r-1;i++)printf("%d",a[i]);printf("%d\n",a[r-1]);}}while(prev_permutation(a,a+n));  //降序对return 0;}


<2> DFS


#include<iostream>  #include<cstring>  #include<cstdio>  #include<algorithm>  using namespace std;  int n, r;  int a[12];  bool visit[12];  //记录当前位置状态,看是否被遍历过   void DFS(int x,int cur){//入口,当前层 if(cur>r)    //当选的数已经足够时,结束第当前搜索,返回到上个搜索执行下一步         return ;      for(int i=x;i>=1;i--)       {          if(!visit[i])  //若未被取过值,则此值可取         {              visit[i]=true;              a[cur]=i;  //记录当前层数据             if(cur==r)   //达到第r层,开始输出             {                  for(int i=1;i<=r;i++)                      printf("%d",a[i]);                  printf("\n");              }              DFS(i-1,cur+1);  //进入下一层             visit[i]=false;  //由于当前层已经取过,再恢复为便利状态,便于上一层变换数字时调用         }      }  } int main()  {        while(~scanf("%d%d",&n,&r))     {          memset(visit,false,sizeof(visit));  //初始化原始状态         DFS(n,1);     }      return 0;  }






原创粉丝点击