Recursive and recursive notes

 

//递归是动态规划、树、二分、分治、图的基础,极为重要。要努力突破这个瓶颈。

/*
一、递推
一个简单的问题:
    有5人坐在一起,当问第5个人多少岁,他说比第4个人大2岁,问第4个人多少岁,他说比第3个人大2岁,
依此下去,问第1个人多少岁,他说他10岁,最后求第5个人多少岁?
    如果所坐的不是5人而是n人,写出第n个人的年龄表达式。
    当n=1时,f(n)=10;
    当n>=2时,f(n)=f(n-1)+2;
    化简得通项f(n)=10+(n-1)*2 (n>=1).

引出背景:由于不是所有的问题都能很轻易的推出通项,如斐波拉契数列,通项极难推导,此时就需要用递归解决。

二、递归(重难点)
    实际上,递归的意思就是,一个函数在执行时再次调用函数本身。
eg.阶乘:
    int fact(int x){ return(x==0)? 1:x*fact(x-1);}
eg.斐波拉契数列:
    int fib(int x){ return(x<=1)? 1:fib(x-1)+fib(x-2);}


三、递推与递归的关系
    递推是一推到底结束;递归是一推到底再推回来,中间会有回溯的过程,把需要解决的问题抽象成一个
简单的子问题,通过递归子问题来最终解决整个问题。
*/

/*斐波拉契递归过程:
F(0)=0
F(1)=1
F(n)=F(n-1)+F(n-2),(n>=2)

int Fib(int num){
    if((num==1)||(num==0)){       //递归出口
        return num;
    }
    return Fib(num-1)+Fib(num-2); //递归体
}                                 //所有的递归程序都由这两部分组成:出口+体
*/

eg1

/* N皇后问题
Problem Description
在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一行,同一列,
也不允许处在与棋盘边框成45度角的斜线上)
你的任务是,对于给定的N,求出有多少种合法的放置方法。
Input
共有若干行,每行一个正整数N<=10,表示棋盘和皇后的数量;如果N=0,表示结束。
Output
共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。
Sample Input
1
8
5
0
Sample Output
1
92
10
*/

#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
#include <cmath>
#include <list>
#include <cstdlib>
#include <cstring>
using namespace std;
int n,sum,vis[5][50];
void dfs(int row){
    if(row==n+1){
        sum++;
        return;
    }
    for(int i=1;i<=n;i++){
        if(vis[0][i]==0&&vis[1][n+i-row]==0&&vis[2][i+row]==0){
            vis[0][i]=vis[1][i-row+n]=vis[2][i+row]=1;
            dfs(row+1);
            vis[0][i]=vis[1][i-row+n]=vis[2][i+row]=0;
        }
    }
}
int main(){
    //int n;
    cin>>n;
    memset(vis, 0, sizeof(vis));
    sum=0;
    dfs(1);
    cout<<sum<<endl;
    return 0;
}

eg2

/* 素数环问题
Problem Description
给你一个n
对1...n n个数排序,1必须在第一位,相邻两个数相加要为素数(1与最后一个数相加也必须为素数)
输出所有满足上述的序列。
Sample Input
6
8
Sample Input
case1:
1 4 3 2 5 6
1 6 5 2 3 4
case2:
1 2 3 8 5 6 7 4
1 2 5 8 3 4 7 6
1 4 7 6 5 8 3 2
1 6 7 4 3 8 5 2
*/

#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
#include <cmath>
#include <list>
#include <cstdlib>
#include <cstring>
using namespace std;
int  n,a[30],vis[30];
int prime[40]={0,1,1,1,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,1,0,1,0,0,0,0,0,1,0,0};
void dfs(int num){
    if(num==n&&prime[a[num-1]+a[0]]){
        for(int i=0;i<num-1;i++){
            printf("%d ",a[i]);
        }
        printf("%d\n",a[num-1]);
    }else{
        for(int i=2;i<=n;i++){
            if(vis[i]==0&&prime[i+a[num-1]]){
                vis[i]=1;
                a[num++]=i;
                dfs(num);
                vis[i]=0;
                num--;
            }
        }
    }
}
int main(){
    int num;
    num=0;
    while(cin>>n){
        memset(vis, 0, sizeof(vis));
        num++;
        printf("Case %d:\n",num);
        a[0]=1;
        dfs(1);
        printf("\n");
    }
    return 0;
}

 

 

 

Released seven original articles · won praise 1 · views 285

Guess you like

Origin blog.csdn.net/qq_45599068/article/details/104083062