3.递归、递推

首先谈谈C++ STL(Standard Template Library)中常用几种数据类型

1. list:双向链表  、基本等同数组   #include    

2.vector:向量、基本等同个数组、和list区别在于存储空间连续   #include

3.queue: 队列、先进先出链表   #include    

4.stack :栈、后进先出链表    #include

5.priority_queue:优先队列、排好序的队列   #include

6.set:集合、排好序的去重的数组   #include

7.map:python中的字典,自动根据关键字排好序   #include

8.其他..... 待了解

参考博客:

      c++STL容器(map,set,vector,stack,queue)

      C++list的使用总结及常用list操作

较常用的是vector、set和map,这些再和结构体组合起来用,美滋滋。自己实验了一下vector实现图邻接链表,map的基本操作

#include
#include
#include
using namespace std;

typedef struct node {
    int data;
    vector index;

};

int main()
{

    struct node graph[100];//创建

    int i,j;
    for(i=0;i<4;i++)  //输入
    {
        graph[i].data=i;
    }
    int v1,v2;
    for(i=0;i<4;i++)
    {
        cout<<"请输入边v1-v2:";
        cin>>v1>>v2;
        graph[v1].index.push_back(v2);
        graph[v2].index.push_back(v1);
    }

    for(i=0;i<4;i++)//输出
        {
            cout<<"顶点"<test;
    test.insert(pair(1, "student_one"));
    test.insert(pair(2, "student_two"));
    test.insert(pair(3, "student_three"));
    map::iterator iter;
    for(iter=test.begin();iter!=test.end();iter++)
        cout<first<<" "<second<t;
    t["a"]= "student_one";
    t["b"] ="student_two";
    t["c"]= "student_three";
   // map::iterator i;
    //for(int i=0;i<2;i++)
        cout<

效果如下:

3.递归、递推_第1张图片3.递归、递推_第2张图片

 

进入正题

-------------------------------------------------------------我是分割线-----------------------------------------------------------------

递归:定义:函数自己调用自己。看完感受:啥玩意?

求阶乘那种简单问题看了等于没看。变换一下又蒙了。先看个题

P1192 台阶问题

这个题递归、递推都能实现。

题解:我要走到第n个台阶,要么从n-1走一步到,或者从n-2跨两阶到,。。。。从n-k阶跨k个台阶到。

也就是说走到n的方案数 S(n)= S(n-1)+ S(n-1)+.....+ S(n-k)(此处需要理解)

这么理解:

假设k=2,当n=1的时候可以从第0个台阶走1步   1种方案。

依次递推:n=2    从0走2步和从1走1步; S(2) = S(1)+S(0) = 1+1 =2;

                  n=3    从1走2步和从2走1步; S(3) = S(2)+S(1) = 2+1 =3;

                                                。。。。。。。。。。。。。

递归代码就可以这么写:

#include
using namespace std;
int n,k;
int digui (int n){
    if(n==0) return 1;
    int sum=0;
    for(int i=1;i<=k;i++)
    {
        if(n-i<0) break;
        sum=(sum + digui(n-i))%100003;//此处为上面推导的公式
    }

    return sum%100003;
}
int main(){


    cin>>n>>k;
    int sum = digui(n);
    cout<

恭喜:20分到手!   4804ms,已经很仁慈了

我感觉自己被骗了,说好的递归呢??

仔细想想,中间好像存在很多重复计算的过程。

比如n = 10, k=3;

n = 10 时,我需要递归 n=9,n=8,n=7

n = 9 时,我需要递归 n=8,n=7,n=6

n = 8 时,我需要递归 n=7,n=6,n=5

       .。。。。。。。。。。

太多重复了!!!!!

我能不能只算一次呢?     状态数组说:没问题啊

思路很简单:每次算之后我把结果保存起来,下次到了先看一下算没算过,算过的话就直接取结果赶紧回家吧。

#include//万能库
using namespace std;
int n,k;
int s[100010];
int digui (int n){
    if(n==0) return 1;
    if(s[n]) return s[n];//算过了,给你数据,赶紧回家吧
    int sum=0;
    for(int i=1;i<=k;i++)
    {
        if(n-i<0) break;
        s[n]=(s[n] + digui(n-i))%100003;
    }

    return s[n]%100003;
}
int main(){


    cin>>n>>k;
    int sum = digui(n);
    cout<

大神看了一下,你这个竟然过了??  10^4 * 10^3,很容易超啊

偷偷告诉你,时间可以降到 10^4,没错,一重循环就够了!

 

递推闪亮登场~

思想很简单:用一个变量保存前n-k到n的和,然后从前往后,每加一个数我就踢掉前面一个。

比如  i从 n-2到n-1,踢掉S(n-2-k),加上S(n-1),这样保证永远是n到n-k,k个结果之和。

有一篇通熟易懂的文章:漫画:什么是动态规划?

#include
using namespace std;
int n,k;
int dp[100010];
int main()
{
    int n,k,i,j;
    cin>>n>>k;
    //for(i=1;i<=k;i++)
        dp[0]=1;
        int sum=dp[0];
    for(i=1;i<=n;i++)
        {
            if(i

 

总结一下递推和递归:

递归:从后往前找解,也就是循环的另外一种实现手段,很暴力,当问题没法确定循环轮数或次数时考虑用递归。

递推:从前往后推导,跟核心公式跟递归一样,只不过保存每一次结果,时间一般比递归快,典型空间换时间。

其实递推和递归都是将问题分解为每一个子问题

基本就思考三个点:结束条件、每一次递归要解决的问题、每一步递归的意义

重点要理解递归执行的全部过程。

 

 

你可能感兴趣的:(算法学习)