算法--递归

算法--递归,第1张

算法--递归

递归

前言题
算法基础


前言

递归 和 递推 很像

递归 把问题分解为子问题 求子问题 从n到1递推 用子问题反推总问题 从1到n

717. 简单斐波那契

这一题 既可以用递归写,也可以用递推写
用这一题来理解递推
在递归中,求f(n) 只需递归调用f(n-1)和f(n-2)
递推写法,先算f(n-1)和f(n-2),再算f(n)

递推写法

#include 
#include 
#include 
#include 

using namespace std;

int main()
{
    int n;
    cin>>n;
    int f[46];
    f[1]=0,f[2]=1;
    for (int i = 3; i <= n; i ++ ) f[i]=f[i-1]+f[i-2];
    
    for (int i = 1; i <= n; i ++ ) cout< 

另一个版本,速度更快

#include 
#include 
#include 
#include 

using namespace std;

int n;
int a,b=1,c;

int main()
{
    scanf("%d",&n);
    while(n--){
        printf("%d ",a);
        c=a+b;
        a=b,b=c;
	}
    return 0;
}

95. 费解的开关(中等)

思路
从第一行开始往下按开关,枚举第一行
每个开关只按一次
顺序不影响

关键点
偏移量表示开关的变化
十进制转二进制

#include 
#include 
#include 
#include 

using namespace std;

const int N = 6;

char g[N][N], backup[N][N];
int dx[5] = {-1, 0, 1, 0, 0}, dy[5] = {0, 1, 0, -1, 0};

void turn(int x, int y)
{
    for (int i = 0; i < 5; i++)
    {
        int a = x + dx[i], b = y + dy[i];
        if (a < 0 || a >= 5 || b < 0 || b >= 5) continue;
        g[a][b] ^= 1;
    }
}

int main()
{
    int T;
    cin >> T;
    while (T -- )
    {
        for (int i = 0; i < 5 ; i++) cin >> g[i];

        int res = 10;
        for (int op = 0; op < 32; op++)
        {
            memcpy(backup, g, sizeof g);
            int step = 0;
            for (int i = 0; i < 5; i++)
                if (op >> i & 1) //将十进制转换为二进制 如果灯是灭的
                {
                    step ++ ;
                    turn(0, i);
                }
            for (int i = 0; i < 4; i++)     //处理第二行
                for (int j = 0; j < 5; j++) //每一列
                    if (g[i][j] == '0') //如果这个灯没开
                    {
                        step++; 
                        turn(i + 1,j); //下一行一定要点
                    }
            //判断最后一行
            bool dark = false;
            for (int i = 0; i < 5; i++)
                if (g[4][i] == '0')
                {
                    dark = true;
                    break;
                }
            if (!dark)  res = min(res, step);
            memcpy(g, backup, sizeof g);
        }
        if (res > 6) res = -1;
        cout << res << endl;
    }
    return 0;
}

116. 飞行员兄弟

思路
暴力枚举 位运算

#include 

#define x first
#define y second

using namespace std;

typedef pair PII;


const int N = 5;

char g[N][N],backup[N][N];

int get(int x,int y)//返回这个位置的下标
{
    return 4 * x + y;
}

void turn_one(int x,int y)//开关翻转
{
    if(g[x][y]=='+')
        g[x][y] = '-';
    else 
        g[x][y] = '+';
}

void turn_all(int x,int y)
{
    for (int i = 0; i < 4;i++)
    {
        turn_one(x, i);//按这一列开关
        turn_one(i, y);//按这一行开关
    }
    turn_one(x, y); //因为x和y 按了偶数次
                    //会保持不变 再按一次 让它翻转
}

int main()
{
    for (int i = 0; i < 4; i ++)
        cin >> g[i];

    vector res;

    for (int op = 0; op < 1 << 16; op++)//枚举所有的操作 1 << 16 是2的16次方
    {
        vector temp;
        memcpy(backup, g, sizeof g);//备份

        // *** 作
        for (int i = 0; i < 4;i++)//遍历每一个位置
            for (int j = 0; j < 4;j++)
            //如果这个开关是 1 的话
                if(op >> get(i,j) & 1)//如果这个 *** 作是该位置 且是打开的
                {
                    temp.push_back({i, j});//存入数组
                    turn_all(i, j);// 这一行 这一列的开关都按一边
                }

        //检查
        bool closed = false;
        for (int i = 0; i < 4; i++)
            for (int  j = 0; j < 4; j++)
            {
                if(g[i][j]=='+')
                    closed = true;
            }
        
        if(closed==false)//所有开关都是关闭的
            if(res.empty() || res.size() > temp.size())//如果当前记录方案步数大于当前 *** 作步数
                res = temp;
        memcpy(g, backup, sizeof g);
    }

    cout << res.size() << endl;
    for(auto op : res)//因为是从 0 开始的
        cout << op.x + 1 << ' ' << op.y + 1 << endl;

    return 0;
}

1208. 翻硬币

思路
一维的费解的开关问题,模拟一下,两个硬笔看作一个开关,每个开关只按一次

#include 

using namespace std;

string a, b;

void turn(int x)
{
    if(a[x] == '*')
        a[x] = 'o';
    else
        a[x] = '*';
}

int main()
{
    cin >> a >> b;
    int res = 0;
    for (int i = 0; i < a.size(); i++)
    {
        if(a[i] != b[i])
        {
            turn(i), turn(i + 1);
            res++;
        }
    }
    cout << res << endl;
}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5714067.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-18

发表评论

登录后才能评论

评论列表(0条)

保存