有关递推与递归的回顾

注:本文为回顾,所以仅会记录本人认为的难点与分析

递推

联系&难度

个人认为,递推与动态规划实际是密不可分的,你说它简单,但到了做题时难以找到转移方程,你要是说它难,但它确确实实是最基本的东西了

例题

斐波那契数列

这是一道最基础的递推题,根据对数列的描述,不难发现,从第3项开始,我们都可以用这样一个式子表示:\(f_i=f_{i-1}+f_{i-2}\)
因而,我们可以直接利用循环得到,代码如下:

#include <iostream>
#include <cstdio>
using namespace std;
int n,a,b[1000001],mmax = 2;
int main(){
	cin >> n;
	b[1] = 1;
	b[2] = 1;
        for (int i = 3;i <= 1000001;i ++)
	  b[i] = (b[i - 1] + b[i - 2]);
	while (n > 0){
		n --;
		cin >> a;
		cout << b[a] << endl;
	}
	return 0;
}

题目传送门:点这里

上台阶

这一道题其实可以看做一道最基础的动态规划,每一步有3个状态,我们可以发现,当楼梯有1层时,仅有1种走法;当楼梯有2层时,有2种走法:走2个1层或1个2层;当楼梯有3层时,有4种走法:一次三层,三次一层,2、1和1,2;再往后,我们可以发现,i层时可行方法为i-1层i-2层i-3层的方法数总和,即\(f_i=f_{i-1}+f_{i-2}+f_{i-3}\),而\(f_1=1,f_2=2,f_3=4\)为边界条件,进行循环,按输入得到结果即可,代码如下:

#include <iostream>
#include <cstdio>
using namespace std;
long long int n,f[72];
int main(){
	f[1] = 1;
	f[2] = 2;
	f[3] = 4;
        for (int i = 4;i <= 71;i ++)
          f[i] = f[i - 1] + f[i - 2] + f[i - 3];
	while (1){
		cin >> n;
		if (n == 0)
		  break;
		cout << f[n] << endl;
	}
	return 0;
}

题目传送门:点这里

流感传染

这一道题则就是一种搜索,其实并没有太大的难度
具体细节详见下方代码:

#include <iostream>
#include <cstdio>
using namespace std;
int n,t[101][101],o[101][101],m,ch[10001][2],last,now,ans; //o在本处并无实际用处,ch为队列,ch[x][0]为行,ch[x][1]为列,last,now分别为队列的头和尾
int main(){
	cin >> n;
	for (int i = 0;i < n;i ++)
	  for (int j = 0;j < n;j ++){
	  	char c;
	  	cin >> c;
	  	if (c == '.')
	  	  t[i][j] = 0;
	  	else if (c == '@'){
	  		o[i][j] = t[i][j] = 1;
		  }
	  	else if (c == '#')
	  	  o[i][j] = t[i][j] = -1;
	  }  //原图的输入
	cin >> m;
	for (int k = 2;k <= m;k ++){ //需从第二天开始进行模拟
		for (int i = 0;i < n;i ++)
		  for (int j = 0;j < n;j ++)
		    if (t[i][j] == 1){ //如果该点为感染者
		    	if (i - 1 >= 0)    //保证不越界
		    	  if (t[i - 1][j] == 0){ //若该点为正常人
		    	    ch[now][0] = i - 1;  //存储坐标
		    	    ch[now][1] = j;
		    	    now ++; //队尾++
			  }
		    	if (j - 1 >= 0)    //同上
		    	  if (t[i][j - 1] == 0){
		    	    ch[now][0] = i;
		    	    ch[now][1] = j - 1;
		    	    now ++;
			  }
			if (t[i + 1][j] == 0){
		    	  ch[now][0] = i + 1;
		    	  ch[now][1] = j;
		    	  now ++;
			  }
			if (t[i][j + 1] == 0){
		    	  ch[now][0] = i;
		    	  ch[now][1] = j + 1;
		    	  now ++;
			}
		}
		for (int i = last;i < now;i ++){
		    t[ch[i][0]][ch[i][1]] = 1;  //将队列所做更改写入图
		}
		last = now;//清空队列
	}
	for (int i = 0;i < n;i ++)   //统计
	  for (int j = 0;j < n;j ++)
	    if (t[i][j] == 1)
	      ans ++;
	cout << ans ;
	return 0;
}

题目传送门:点这里

递归(搜索与回溯)

联系&难度

搜索与回溯,即深度优先搜索(DPS),属于递归的一种,而且,许多递推可做的题目同样可用递归做出,如:斐波那契数列

例题

八皇后问题

这一道题可以说是十分基础了,基本是必会的题目,主体思想很简单,从第一个皇后的位置进行选择,然后依次判断此行每个位置是否可以放下,如果是,进行递归,如果不行,判断下一位置,然后进行回溯

#include<iostream>
#include<cstdio>
using namespace std;
int a[30];
int b[30];
int c[30];
int d[30];
int flag=0;
void print()
{
    flag++;
    cout<<"No. "<<flag<<endl;
    for(int i=1;i<=8;i++)
    {
        for(int j=1;j<=8;j++)
        {
            if(a[j]==i)
                cout<<"1 ";
            else
                cout<<"0 ";
        }
        cout<<endl;
    }
}
void searchh(int i)
{
    for(int j=1;j<=8;j++)
    {
        if((!b[j])&&(!c[i+j])&&(!d[i-j+7]))
        {
            a[i]=j;
            b[j]=1;
            c[i+j]=1;
            d[i-j+7]=1;
            if(i==8) print();
            else searchh(i+1);
            b[j]=0;
            c[i+j]=0;
            d[i-j+7]=0;
        }
    }
}
int main()
{
    searchh(1);
    return 0;
}

题目传送门:点这里

更新日志

  • 2020.5.16 完成编辑

日后优化持续跟进

posted @ 2020-05-16 17:43  Dfkuaid  阅读(160)  评论(0编辑  收藏  举报