今天看了吴永辉老师讲的递归与回溯的编程课,记录一下。(本来想把课件发出来的,不知道怎么发)
递归的回溯定义就不再多说了,直接看题吧。
1、计算递归函数的实验范例
计算递归函数的实验范例的大致解题思路。
放苹果 POJ 1664 http://poj.org/problem?id=1664
递归式
老师的思路写的非常棒,如图。
下面是我个人整理后用自己的语言叙述的:
-
设f(m,n)是m个苹果放在n个盘子李的总共放法数量。 首先很容易分成两种情况,n>m,n<m;
-
n>m 盘子数大于苹果数,故肯定有n-m个盘子空着也就是对放法无影响,根据题意 1 5 1 与5 1 1是同一种方法可知,与放得顺序无关,故f(m,n)=f(m,m);
-
n<=m时,可以分为有空盘子,和没有空盘子两种情况。
-
有空盘子即f(m,n-1),我开始并没理解为啥n-1,感觉它可以空好多盘子,后来才逐渐意识到它是递归,所以一直递归下去,就将空1个盘子,空2个盘子…空n个盘子的情况都枚举出来了。
-
无空盘子,即f(m-n,n),即每个盘子至少放一个,还剩下m-n个苹果没放,故f(m,n)的放法数,取决于剩下m-n个苹果放在n个盘子里的放法数。
递归边界
有了这些我们就可以愉快的敲代码了。
AC代码
#include<iostream>
using namespace std;
int dfs(int m,int n)
{
if(n==1||m==0)
return 1;
if(n>m)
return dfs(m,m);
else{
return dfs(m,n-1) + dfs(m-n,n);
}
}
int main()
{
int n,m,t;
cin>>t;
while(t--){
cin>>m>>n;
cout<<dfs(m,n)<<endl;
}
return 0;
}
2、求解递归数据的实验范例
Symmetric Order POJ 2013 http://poj.org/problem?id=2013
题目大意
试题解析
非递归方法
老师的描述
个人的描述
如图竖线代表在上方,横线代表在下方,上方均为从第1行开始隔行输出,下方很容易发现,偶数行时下方是从第n行开始隔行输出的,奇数行时是从n-1行开始输出的。
所以很容易的出代码
非递归AC代码
#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
int main()
{
int n,cnt=0;
string str[1000];
while(~scanf("%d",&n) && n != 0)
{
cnt++;
for(int i = 1 ; i <= n ; i++ )
{
cin>>str[i];
}
cout<<"SET "<<cnt<<endl;
for(int i = 1 ; i <= n ; i+=2 )
{
cout<<str[i]<<endl;
}
if(n%2==0){
for(int i = n ; i>=2 ; i-=2 ){
cout<<str[i]<<endl;
}
}else{
for(int i = n-1; i>=2 ; i-=2){
cout<<str[i]<<endl;
}
}
}
return 0;
}
递归方法
老师的描述
个人的描述
将n个字符串分为 s[1]s[2] 、s[3]s[4]…s[n-1]s[n] n/2组,将s[1]、s[3]…s[n-1]直接输出,剩下的进行递归,递归类似与压栈,故输出为s[n] … s[4] s[2];递归边界易知当n为0时;
递归AC代码
#include<iostream>
using namespace std;
void dfs(int n)
{
string s;
cin>>s; //每组的第一个直接输出
cout<<s<<endl;
if(--n){
//判断这一组是否成对,即每组的第二个元素是否存在
cin>>s;
if(--n) dfs(n); //若后面还有其它组着压栈,没有直接输出,开始出栈。
cout<<s<<endl;
}
}
int main()
{
int n,cnt=0;
while(cin>>n){
if(n==0) break;
cnt++;
cout<<"SET "<<cnt<<endl;
dfs(n);
}
}
3、用递归算法求解问题的实验范例
Fractal POJ 2083 http://poj.org/problem?id=2083
题目大意:
题目解析
个人描述:
根据题目的样例,很容易知道n度的盒分形图的规模为3^(n-1)的正方形,n-1度的盒分形分别位于左上,左下,右上,右下,中间。x,y为左上角坐标,然后进行对应坐标运算递归即可。
AC代码
#include<iostream>
#include<cmath>
#include<cstring>
using namespace std;
char mp[735][735];
void dfs(int n , int x,int y)
{
if(n==1){
mp[x][y]='X';
return ;
}
int m = pow(3,n-2); //注意3^(n-2)
dfs(n-1,x,y);///左上角
dfs(n-1,x,y+2*m);//右上角
dfs(n-1,x+m,y+m);//中间
dfs(n-1,x+2*m,y);//左下角
dfs(n-1,x+2*m,y+2*m);///右下角
}
int main()
{
int n;
while(cin>>n){
if(n==-1) break;
memset(mp,' ',sizeof(mp)); ///注意初始化,否则会wa
dfs(n,1,1);
int m=pow(3,n-1);
for(int i = 1 ; i<=m;i++)
{
for(int j = 1 ; j<=m ;j++)
cout<<mp[i][j];
cout<<endl;
}
cout<<"-"<<endl;
}
return 0;
}
没写全,想要全部课件的可以私信我。