递归是程序设计中的一种算法。
有些数据结构(如二叉树),其自身就有递归的性质,有些问题其自身没有明显递归结构,单用递归求解更简单。
递归算法具有天生的低效率问题。
1.一个射击运动员打靶,靶一共10环,连开10枪打中90环的可能性有多少种?递归编程实现。
代码:
#include<iostream>
using namespace std;
int sum; //统计次数
int store[10];//记录十次打靶得分
void Output(){
for(int i=9;i>=0;i--){
cout<<store[i]<<" "; //输出每一种可能
}
cout<<endl;
++sum;
}
void Comput(int score,int num){
if(score<0||score>(num+1)*10)//次数unm为0~9 出现这种情况,即便后面每枪10环也不能满足就退出递归
return;
if(num==0){
store[num]=score;
Output();
return;
}
for(int i=0;i<=10;i++){ //每靶10环
store[num]=i;
Comput(score-i,num-1);
}
}
int main(){
Comput(90,9);
cout<<"总数:"<<sum<<endl;
return 0;
}
2.八皇后问题是一个古老而著名的问题,是回溯算法的典型例题。在国际象棋盘上排放八个皇后使其不能相互攻击,即任意两个皇后都不能处于同一行,同一列或同一斜线上,问有多少种摆法。
一种8皇后的摆法:
0 0 0 0 0 0 0 1
0 0 0 1 0 0 0 0
1 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0
0 0 0 0 0 1 0 0
0 1 0 0 0 0 0 0
0 0 0 0 0 0 1 0
0 0 0 0 1 0 0 0
#include<stdio.h> //#include<memory.h> static int Queen[8][8]; static int a[8]; //标记列冲突 static int b[15]; //标记主对角线冲突 b[i-j+7] static int c[15]; //标记从对角线冲突 c[i+j] static int QueenNum=0;//记录总的棋盘状态数 void qu(int i); //参数i代表行 int main() { //初始化棋盘 为0 放置棋子的位置为1 for(int i=0;i<8;i++){ a[i]=0; //初始化标记 for(int j=0;j<8;j++){ Queen[i][j]=0; } } for(int i=0;i<15;i++){ b[i]=0; } qu(0); return 0; } void qu(int i){ for(int iColum=0;iColum<8;iColum++){ if(a[iColum]==0&&b[i-iColum+7]==0&&c[i+iColum]==0) //无冲突 { Queen[i][iColum]=1; a[iColum]=1; //标记,下一次该列上不能放 b[i-iColum+7]=1; //标记,下一次该主对角线上不能放 c[i+iColum]=1; //标记,下一次该从对角线上不能放 if(i<7)qu(i+1); else{ //输出棋盘状态 int iLine,iColum; printf("第%d种状态为:\n",++QueenNum); for(iLine=0;iLine<8;iLine++){ for(iColum=0;iColum<8;iColum++){ printf("%d ",Queen[iLine][iColum]); } printf("\n"); } printf("\n\n"); } //如果前次皇后的放置导致后面的放置无论如何都不能满足,则回溯 Queen[i][iColum]=0; a[iColum]=0; b[i-iColum+7]=0; c[i+iColum]=0; } } }
3.编写一个程序,把字符串中的所有字符子串的各种组合形式都显示出来,顺序不同字母相同的看作一种组合。
#include<stdio.h> #include<string.h> #include<stdlib.h> int sum=0; char str[]="hart"; //待分解字符串 int length; //字符串长度 char *out; //结果字符串 void DoCombine(char in[],char out[],int length,int rec,int start){ int i; for(i=start;i<length;i++){ out[rec]=in[i]; out[rec+1]=0; printf("%s\n",out); if(i<length-1) DoCombine(in,out,length,rec+1,i+1); } } int main(){ length=strlen(str); out=(char*)malloc(length+1); DoCombine(str,out,length,0,0); return 0; }
4.0-1背包问题
输入两个整数n和m,从数列1,2,3...,n中随意取几个数,使其和等于m,要求将其中所有的可能的组合列出来,编程求解。
#include<iostream> #include<cstring> using namespace std; int mVal,nVal; //mVal是目标容量 n是物品最大重量 int *pOut; void calFun(int m,int n){ if(m<1||n<1||(n==1&&m!=1)) return; //递归出口 if(m==n){ pOut[n]=1; for(int i=1;i<=nVal;++i){ if(pOut[i]){ cout<<i<<" "; } } cout<<endl; pOut[n]=0; } calFun(m,n-1); //不取n pOut[n]=1; calFun(m-n,n-1); //取n pOut[n]=0; } int main(){ cout<<"m=:"; cin>>mVal; cout<<"n=:"; cin>>nVal; if(mVal<nVal)nVal=mVal; //比较n,m哪个大 因为n>m的话n与m之间的数是没有意义的 pOut=new int[nVal+1]; memset(pOut,0,(nVal+1)*sizeof(int)); calFun(mVal,nVal); delete []pOut; return 0; }
概率:
5.给出下面程序的输出
#include<stdlib.h>
#include<stdio.h>
#define LOOP 1000
int mian(){
int rgnC=0;
for(int i=0;i<LOOP;i++){
int x=rand();
int y=rand();
if(x*x+y*y<RAND_MAX*RAND_MAX)rgnC++;
}
printf("%d\n",rgnC);
return 0;
}
RAND_MAX是随机数中的最大值,也就相当于圆的最大半径R,x和y是某点的横纵坐标,他们的平方和就是到原点的距离,上诉问题就退化成随机正方形里落1000个点,落在半径里面的点有多少个。
求落点可能性之比就是求一个1/4圆面积和一个正方形面积之比。
1/4圆的面积:(1/4)*π*r*r
正方形的面积:r*r
两者之比:π/4≈785