遞歸算法:直接或間接調用自身的算法。
遞歸函數:用函數自身給出定義的函數。
遞歸的優點:算法簡潔易於分析理解。
遞歸的缺點:分支較多的函數時間、空間複雜度太大。
例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;
}