版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chengchencheng/article/details/82464705
递归算法:直接或间接调用自身的算法。
递归函数:用函数自身给出定义的函数。
递归的优点:算法简洁易于分析理解。
递归的缺点:分支较多的函数时间、空间复杂度太大。
例1:求n!
#include<iostream>
using namespace std;
int f(int n);
int main(){
int m;
cin>>m;
cout<<f(m)<<endl;
return 0;
}
int f(int n){ //递归部分
if(n == 1)
return n;
else
return n*f(n-1);
}
例2:求最大公约数(辗转相除法)
#include<iostream>
using namespace std;
int gcd(int a, int b);
int main(){
int x, y;
cin>>x>>y;
cout<<gcd(x, y)<<endl;
return 0;
}
int gcd(int a, int b){
if(b == 0)
return a;
else
return gcd(b, a%b);
}
例3:穷举n位二进制数
#include<iostream>
using namespace std;
void dfs(int n);
void output();
int arr[20];
int m;
int main(){
cin>>m;
dfs(0);
return 0;
}
void dfs(int n){
if(n == m) //达到要求穷举的位数,输出当前数组中的数据
output();
else
for(arr[n] = 0; arr[n] < 2; arr[n]++){ //依次在数组中储存0或1
dfs(n+1); //递归搜索下一位数字
}
}
void output(){
int i;
for(i = 0; i < m; i++){
cout<<arr[i];
}
cout<<endl;
}
例4:四皇后问题
要求每一皇后所在行,列,斜线 y=x, y=-x方向bu'n不能有其他皇后,无输入,输出四个皇后都可放置的可能的排列方式。
#include<iostream>
using namespace std;
void dfs(int n);
void output();
int cannot_do(int row, int col);
int arr[10];
int main(){
dfs(0);
for(int i = 0; i < 4; i++){ //数组初始化,以免影响结果
arr[i] = 9;
}
return 0;
}
void dfs(int n){
if(n == 4)
output();
else
for(arr[n] = 0; arr[n] < 4; arr[n]++){ //遍历四列
if(!cannot_do(n, arr[n])){ //若在该列可放下一个皇后,递归搜索下一层
dfs(n+1);
}
}
}
int cannot_do(int row, int col){
int i;
for(i = 0; i < row; i++){ //若在之前任一皇后所在列或斜线上,均不可放新皇后
if(arr[i] == col || ((row - i) == (col - arr[i]) || (i - row) == (col - arr[i]) && !(arr[i] == 9)))
return 1;
}
return 0;
}
void output(){ //输出符合条件的放置方法
int i;
for(i = 0; i < 4; i++){
cout<<arr[i];
}
cout<<endl;
}
例5:骨牌组合
由0-6组成00,01,.……,06,11,……,16,……,22,……,66,共28个数字组合,分别编号为0,1,2,……,27.将这28块骨牌排列为7*8的矩阵,将矩阵输入。要求输出可能的骨牌组合情况。
#include<iostream>
using namespace std;
void dfs(int n);
void init();
void output();
int cando(int m, int dire);
int find(int a, int b);
int pre_map[10][10]; //原始输入地图
int arr_map[10][10]; //注册地图
bool map_used[60];
bool data_used[30];
int main(){
init();
dfs(0);
}
void dfs(int n){
int x1, y1, x2, y2;
if(n == 56)
output();
else{
if(!map_used[n]){
x1 = n/8; y1 = n%8; //该数在地图中所在行列
map_used[n] = true; //第n个数已被匹配
for(int i = 0; i < 2; i ++){ //0为向右搜索,1为向下搜索
if(cando(n, i)){//被匹配数未被使用且组合未被注册
if(i == 0){ //匹配的数在地图中所在行列
x2 = x1; y2 = y1+1;
}
else{
x2 = x1+1; y2 = y1;
}
map_used[x2*8 + y2] = true; //被第n个数匹配
int t = find(pre_map[x1][y1], pre_map[x2][y2]); //找出这对数所在组合编号
arr_map[x1][y1] = t; //在匹配地图上注册
arr_map[x2][y2] = t; //在匹配地图上注册
data_used[t] = true; //标记组合被使用
dfs(n+1);
map_used[x2*8 + y2] = false;
data_used[t] = false;
}
}
map_used[n] = false;
}
else{
dfs(n+1);
}
}
}
int cando(int m, int dire){
int x1, x2, y1, y2;
x1 = m/8; y1 = m%8;
if((x1 == 6 && dire == 1) || (y1 == 7 && dire ==0))
return 0;
if(dire == 0){
x2 = x1; y2 = y1 + 1;
}
else{
x2 = x1 + 1; y2 = y1;
}
if(map_used[x2*8 + y2] == false && data_used[find(pre_map[x1][y1], pre_map[x2][y2])] == false)
return 1;
return 0;
}
void init(){
int i, j;
for(i = 0; i < 7; i++)
for(j = 0; j < 8; j++){
cin>>pre_map[i][j];
arr_map[i][j] = 0;
}
for(i = 0; i < 56; i++)
map_used[i] = false;
for(i = 0; i < 28; i++)
data_used[i] = false;
}
int find(int a, int b){
int c;
if(a > b){
c = a; a = b; b = c;
}
if(a == 0)
return(b);
else if(a == 1)
return(b+6);
else if(a == 2)
return(b+11);
else if(a == 3)
return(b+15);
else if(a == 4)
return(b+18);
else if(a == 5)
return(b+20);
else
return(27);
}
void output(){
int i, j;
cout<<endl;
for(i = 0; i < 7; i++){
for(j = 0; j < 8; j++){
cout<<arr_map[i][j]<<" ";
}
cout<<endl;
}
}
例6.踩气球
描述:六一儿童节,小朋友们做踩气球游戏,气球的编号是1~100,两位小朋友各踩了一些气球,要求他们报出自己所踩气球的编号的乘积。现在需要你编一个程序来判断他们的胜负,判断的规则是这样的:如果两人都说了真话,数字大的人赢;如果两人都说了假话,数字大的人赢;如果报小数字的人说的是真话而报大数字的人说谎,则报小数字的人赢(注意:只要所报的小数字是有可能的,即认为此人说了真话)。
输入:输入为两个数字,0 0表示结束;
输出:输出为获胜的数字。
输入样例:
36 62 49 343 0 0
输出样例:
62 49
#include<iostream>
#include<string.h>
#include<math.h>
using namespace std;
int judge(int t);
int m, n, x, y;
int used[101];
int main(){
while(cin >> n >> m && n){
memset(used, 0, sizeof(used));
x = judge(m);
y = judge(n);
if(x == y){
cout << max(m,n) <<endl;
}
else{
cout << min(m,n) <<endl;
}
}
}
int judge(int t){
if(t == 1) return 1;
for(int i = 1; i <= 100; i++){
if(t%i){
continue;
}
if(used[i]){
continue;
}
else{
used[i] = 1;
if(judge(t/i)) return 1;
used[i] = 0;
}
}
return 0;
}