递归与递推
算法介绍
有些目标是宏大的,比如要在 IOI 赛场中得到满分(俗称 AK IOI)。如果你现在还是一个普通的学生,那么想达成这个目标太难了。但把这样宏大的目标分解为很多个子任务,就没觉得那么复杂了。
要想 AK IOI,只需要入选国家队,参加 IOI 即可。那怎么成为入选国家队呢?参加中国队选拔赛并通过面试答辩即可。使用同样的思路往前倒推,直到最后只剩下最基础的任务(比如认真的读完这章内容并完成练习),做完这样的小任务就很简单了。
像这样将一个很大的任务分解成规模小一些的子任务,子任务分成更小的子任务,直到遇到初始条件,最后整理归纳解决大任务的思想就是递推与递归思想,不过这两者还是有一些区别。
这一章涉及的内容是动态规划思想与分治策略的基础,大家也要认真学习啦,说不定目标就真的达到了。
题目
#include <iostream>
using namespace std;
long long f[30][30],g[30][30];
int dx[]={0,2,1,-1,-2,-2,-1,1,2};//定义偏移数组
int dy[]={0,1,2,2,1,-1,-2,-2,-1};//定义偏移数组
int main()
{
int x,y,n,m;
cin>>x>>y>>n>>m;
for(int i=0;i<9;i++)
{
int a=n+dx[i],b=m+dy[i];
if(a<0||b<0)//检查是否越界
{
continue;
}
g[a][b]=1;
}
for(int i=0;i<=x;i++)
{
for(int j=0;j<=y;j++)
{
if(g[i][j]==1) f[i][j]=0;
else if(i==0&&j==0) f[i][j]=1;
else if(i==0) f[i][j]=f[i][j-1];
else if(j==0) f[i][j]=f[i-1][j];
else f[i][j]=f[i-1][j]+f[i][j-1];
}
}
cout<<f[x][y];
return 0;
}
Function
这是一道简单递归问题,只要按照题目要求做就能做出来,代码如下:
#include <iostream>
using namespace std;
long long f[25][25][25];
long long w(long long a,long long b,long long c)
{
if(a<=0||b<=0||c<=0)
{
return 1;
}
else if(a>20||b>20||c>20)
{
return w(20,20,20);
}
if(f[a][b][c]!=0)
{
return f[a][b][c];
}
else if(a<b&&b<c)
{
return f[a][b][c]=w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,c);
}
else return f[a][b][c]=w(a-1,b,c)+w(a-1,b-1,c)+w(a-1,b,c-1)-w(a-1,b-1,c-1);
}
int main()
{
long long a,b,c;
while(cin>>a>>b>>c)
{
if(a==-1&&b==-1&&c==-1)
{
break;
}
long long ans=w(a,b,c);
printf("w(%lld, %lld, %lld) = %lld\n",a,b,c,ans);
}
return 0;
}
#include <iostream>
using namespace std;
char a[120];
void move(int from,int to)//move函数实现移动的操作
{
for(int i=0;i<2;i++)
{
a[to+i]=a[from+i];
a[from+i]='-';
}
cout<<a+1<<endl;
}
void f(int n)
{
if(n==4)//如果棋子数小于4的话,就按照如下规律操作
{
move(4,9);
move(8,4);
move(2,8);
move(7,2);
move(1,7);
return ;
}
move(n,2*n+1);//如果棋子数大于4,就尽可能把这些棋子通过移动,也变成有4个棋子,就好移动了
move(2*n-1,n);
f(n-1);
}
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
a[i]='o';//将a[i]位置初始化成"o"
a[n+i]='*';//将a[n+i]位置初始化成"*"
}
a[2*n+1]=a[2*n+2]='-';//将a[2*n+2]位置初始化成"-"
cout<<a+1<<endl;
f(n);
return 0;
}
#include <iostream>
using namespace std;
string s;
long long f(long long n,long long k)
{
if(k<=s.size()) return k;
n=n/2;
if(k<=n) return f(n,k);
k=k-n-1;
if(k<=0) k=n;
return f(n,k);
}
int main()
{
long long n,k;
cin>>s>>k;
n=s.size();
while(n<k) n*=2;
long long x=f(n,k);
cout<<s[x-1];
return 0;
}