当前位置: 首页 > web >正文

递归进阶之全排列、组合

1.排列组合

排列:从n个元素中任取m个元素,按照一定的顺序排列起来,叫做m的全排列。

组合:从n个元素中任取m个元素为一组,m个数的组合。

注意: 排列有序,组合无序。

例:从[1,2,3]三个元素中任取两个元素进行排列组合:

排列的结果:[1,2] 、[1,3]、[2,1]、[2,3]、[3,1]、[3,2]

组合的结果:[1,2]、[1,3]、[2,3]

例题:n个元素的全排列,(n互不相同,即1,2,······n).

#include<iostream>
#include<cmath>
using namespace std;  
//n个数全排列 :一定要知道在第几层,该数现在的状态,回溯时的状态 int n;
int a[1000];
bool flag[1000];
void dfs(int k){if(k==n+1){  //递归结束条件,当到达第n+1层,代表第n层已经填完 for(int i=1; i<=n; i++){cout<<a[i]<<" ";}cout<<endl; return;}for(int i=1; i<=n; i++){  //n个数字 if(flag[i]==0){  //当前数字没用过才可以排列 a[k]=i;   //第k层(第k个位置)填数字iflag[i]=1;  //该数已经用过,置为1dfs(k+1);    //填下一层(下一个位置)flag[i]=0;   //递归回来的时候需要重新置为0 }}}int main(){cin>>n;dfs(1);  //从第一层(第一个位置)开始排列 return 0;
}

程序运行结果如下:

例2:n个数选m个数全排列

#include<iostream>
#include<cmath>
using namespace std;  
//n个数选m个数全排列 :一定要知道在第几层,该数现在的状态,回溯时的状态 int n,m;
int a[1000];
bool flag[1000];
void dfs(int k){if(k==m+1){  //递归结束条件,当到达第m+1层,代表第m层已经填完 for(int i=1; i<=m; i++){cout<<a[i]<<" ";}cout<<endl; return;}for(int i=1; i<=n; i++){  //n个数字 if(flag[i]==0){  //当前数字没用过才可以排列 a[k]=i;   //第k层(第k个位置)填数字iflag[i]=1;  //该数已经用过,置为1dfs(k+1);    //填下一层(下一个位置)flag[i]=0;   //递归回来的时候需要重新置为0 }}}int main(){cin>>n>>m;dfs(1);  //从第一层(第一个位置)开始排列 return 0;
}

程序运行如下:

例3:n个不同的元素,任取m个数进行组合。(组合无序)

#include<iostream>
#include<cmath>
using namespace std;  
//n个数选m个数组合 :当前位置数值比前一个数至少大1,
//a[k]代表当前位置上的值,它的范围是[a[k-1]+1,n] int n,m;
int a[1000];void dfs(int k){if(k==m+1){  //递归结束条件,当到达第m+1层,代表第m层已经填完 for(int i=1; i<=m; i++){cout<<a[i]<<" ";}cout<<endl; return;} //当前位置数值比前一个数至少大1,a[k]代表当前位置上的值,它的范围是[a[k-1]+1,n] for(int i=a[k-1]+1; i<=n; i++){  a[k]=i;   //第k层(第k个位置)填数字idfs(k+1);    //填下一层(下一个位置)}
}int main(){cin>>n>>m;dfs(1);  //从第一层(第一个位置)开始排列 return 0;
}

程序运行如下:

2.铺骨牌问题

有一个1*n的长方形,用1*1、1*2、1*3的骨牌铺满方格,共有几种铺法。

分析如下:

本题采用递归函数,当确定最后一块方式后,只需看前面的格子共有几种铺法即可。而最后一个格子的铺法不确定,所以要各种方案的总方案数相加才行。

即:f(n)=f(n-1)+f(n-2)+f(n-3).

程序如下:

#include<iostream>
#include<cmath>
using namespace std;  
int f(int x){if(x==1) return 1;  if(x==2) return 2;if(x==3) return 4;return f(x-1)+f(x-2)+f(x-3);  //共三种格子 //f(x)的方案数为 末尾放1*1,前面总方案为f(x-1);//尾放1*2,前面总方案为f(x-2); 尾放1*3,前面总方案为f(x-3)  
}
int main(){int n;cin>>n;cout<<f(n); return 0;
}

总结

本文简单介绍了排列组合的一些基本做题思路,全排列一定要注意当前位置在第几层,当前数字是否用过,并注意回溯时数字的状态。

感谢:https://zhuanlan.zhihu.com/p/614206522

http://www.xdnf.cn/news/19695.html

相关文章:

  • JS箭头函数
  • 数字铁流:2025.9.3国庆大阅兵系统架构解析
  • 贪心算法解决固定长度区间覆盖问题:最少区间数计算
  • OpenCV 实战:图像模板匹配与旋转处理实现教程
  • G156HAN04.0 宽温域高亮工业屏技术白皮书
  • Spring Ioc —— 集合类型的依赖注入
  • Next.js渲染模式:SSR、SSG与ISR揭秘
  • 第六章:健壮Go应用:工程实践与生产就绪之测试
  • 旧实例数据库损坏sqlserver启动失败解决办法
  • Java PDF转多种图片格式:技术实践与性能优化
  • CS25FTFR010 1225 0.01R/10mR有哪些优势-华年商城
  • 联邦学习论文分享:Federated Learning via Synthetic Data
  • 搭建APP应用程序如何选择服务器
  • 选择图片转base64格式组件简单封装-Base64ImageInpu
  • 【Node.js教程】Express框架入门:从搭建到动态渲染商品列表
  • 埃文科技亮相2025中部数字经济产业发展大会暨数智创新博览会
  • 数据库事务隔离级别与 MVCC 机制详解
  • MiniCPM-V 4.5实战,实现图片、视频、多图的推理
  • 如何使用 JMeter 进行接口测试。
  • 设计模式-状态模式 Java
  • 盲盒小程序系统开发:构建盲盒社交新生态
  • api验签
  • Unity 串口通讯2 硬件SDK 开发[数据监听,按键监听]
  • 前端静态资源缓存与部署实践总结
  • 纯代码实现登录页面的DIY
  • 从零开始的python学习——函数(1)
  • uni-app支持单多选、搜索、查询、限制能否点击组件
  • SpringBoot @RefreshScope 注解的极致玩法
  • 从零开始的云计算生活——第五十五天,黑云压城,kubernetes模块之网络组件和CoreDNS组件
  • 一次诡异的报错排查:为什么时间戳变成了 ١٧٥٦٦٣٢٧٨