目录
概念
作用
例题
例题一:汉诺塔
#include <iostream>
using namespace std;
void Hanoi(int n,char src,char mid,char dest){
if(n==1)
cout<<src<<"->"<<dest<<endl;
else{
Hanoi(n-1,src,dest,mid);
cout<<src<<"->"<<dest<<endl;//A只剩最下面的1个盘子,直接移到C中
Hanoi(n-1,mid,src,dest);
}
}
int main()
{
int n;
cin>>n;
Hanoi(n,'A','B','C');
return 0;
}
例题二:N皇后
#include <iostream>
#include <stdlib.h>
using namespace std;
int n;
int queen[100];//用在存放算好的皇后所在列的位置
void NQueen(int k){//在0~k-1行皇后摆好的前提下,摆第n行皇后
int i,j;
if(k==n){//n个皇后已经摆好
for(i=0;i<n;i++)
//数组中列数从0开始,因此+1
cout<<queen[i]+1<<" ";
cout<<endl;
return;
}
for(i=0;i<n;i++){//摆第k个皇后
for(j=0;j<k;j++){
//和已经摆好的k-1和皇后比较位置是否冲突
if(queen[j]==i||abs(queen[j]-i)==abs(j-k))
break;//冲突,则测试下一个位置
}
if(j==k){//当前选的位置i不冲突
queen[k]=i;//把第k个皇后摆在第i列
NQueen(k+1);//再摆k+1个皇后
}
}
}
int main()
{
cin>>n;
NQueen(0);//从第0行开始摆皇后
return 0;
}
例题三:表达式求值
如图所示,递归定义表达式、项、因子
#include <iostream>
#include <cstring>
#include <cstdlib>
using namespace std;
int expression();
int factor(){//读入一个因子,返回其值
int result=0;
char c=cin.peek();
if(c=='('){//因子是(
cin.get();
result=expression();
cin.get();
}
else{//因子是数字字符
while(isdigit(c)){
result=10*result+c-'0';//c-'0'得到数字字符代表的数值
cin.get();//从输入流中去掉这个数字字符
c=cin.peek();//读取下一个字符
}
}
return result;
}
int term(){//读入一个项,返回其值
int result=factor();//求第一个因子的值
bool flag=true;
while(flag){
char op=cin.peek();
if(op=='*'||op=='/'){//说明*/符号后还有一个因子要处理
cin.get();
int value=factor();
if(op=='*')
result*=value;
else
result/=value;
}
else
flag=false;
}
return result;
}
int expression(){//读入一个表达式,返回其值
int result=term();//求第一项的值
bool flag=true;
while(flag){
char op=cin.peek();//查看一个字符,但不取走
if(op=='+'||op=='-'){//说明+-符号后还有一个项要处理
cin.get();//从输入中读取一个字符
int value=term();
if(op=='+')
result+=value;
else
result-=value;
}
else
flag=false;//后续没有项要处理了
}
return result;
}
int main()
{
cout<<expression()<<endl;
return 0;
}
例题四:爬楼梯
n级台阶的走法=先走一级后,n-1级台阶的走法+先走两级后,n-2级台阶的走法
f(n) = f(n-1)+f (n-2)
边界条件:n<0,0;n=0,1
#include <iostream>
using namespace std;
int walk(int n){
if(n<0)
return 0;
if(n==0)
return 1;
return walk(n-1)+walk(n-2);
}
int main()
{
int n;
cin>>n;
cout<<walk(n)<<endl;
return 0;
}
例题五:放苹果
设i个苹果放在k个盘子里放法总数是f(i,k),则:
k>i时,f(i,k) = f(i,i)
k<=i时,总放法=有盘子为空的放法+没盘子为空的放法
f(i,k) = f(i,k-1) + f(i-k ,k)
边界条件:n=0,f=0;m=0,f=1;
#include <iostream>
using namespace std;
int f(int m,int n){
//m是苹果数,n是盘子数
if(n>m)
return f(m,m);
if(m==0)
return 1;
if(n==0)
return 0;
return f(m,n-1)+f(m-n,n);
}
int main()
{
int t,m,n;
cin>>t;
while(t--){
cin>>m>>n;
cout<<f(m,n)<<endl;
}
return 0;
}
例题六:算24
输入
输出
n个数算24,必有两个数要先算。
这两个数算的结果,和剩余n-2个数,就构成了n-1个数求24的问题(规模变小)
枚举先算的两个数,以及这两个数的运算方式。
边界条件:一个数算24可以直接判断能否算出24
注意:浮点数比较是否相等,不能用==
#include <iostream>
#include <cmath>
using namespace std;
double a[5];
#define EPS 1e-6
bool isZero(double x){
//判断浮点数x的绝对值是否小于1e-6,小于的话可以近似为0
return fabs(x)<=EPS;
}
bool count(double a[],int n){
//用a[]里的n个数计算24
if(n==1){
if(isZero(a[0]=24))
return true;
else
return false;
}
double b[5];
//枚举两个数的组合
for(int i=0;i<n-1;i++){
for(int j=i+1;j<n;j++){
int m=0;//剩余m个数,m=n-2
for(int k=0;k<n;k++)
if(k!=ij)
b[m++]=a[k];//把其余数放入b[]
//运算a[i],a[j],把结果放入b[m]
b[m]=a[i]+a[j];
if(count(b,m+1));
return true;
b[m]=a[i]-a[j];
if(count(b,m+1))
return true;
b[m]=a[j]-a[i];
if(count(b,m+1))
return true;
b[m]=a[i]*a[j];
if(count(b,m+1))
return true;
if(!isZero(a[j])){
b[m]=a[i]/a[j];
if(count(b,m+1))
return true;
}
if(!isZero(a[i])){
b[m]=a[j]/a[i];
if(count(b,m+1))
return true;
}
}
}
return false;
}
int main()
{
while(true){
for(int i=0;i<4;i++)
cin>>a[i];
if(isZero(a[0]))
break;
if(count(a,4))
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
return 0;
}