寒假刷题-递归与递推

news2024/11/18 22:32:16

寒假刷题

92. 递归实现指数型枚举

image-20240115182149547

image-20240115182203169

解法1递归

使用递归对每一个坑位进行选择,每个坑位有两种选择,填或者不填,使用st数组来记录每个坑位的状态,u来记录已经有多少坑位有了选择。

image-20240115194744258

每个坑位有2钟选择,n个坑位的复杂度就是2的n次方。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 16;
int n;
int st[N];
void dfs(int u){
    if(u>n)
    {
        for(int i = 1;i<=n;i++)
        {
            if(st[i]==1)printf("%d ",i);
        }
        printf("\n");
        return;
    }
    st[u] = 1;
    dfs(u+1);
    st[u]=0;
    dfs(u+1);
}
int main(){
    scanf("%d",&n);
    dfs(1);
    return 0;
}

坑位的下标和这个坑位的数字是存在对应关系的,所以可以用一个u来控制递归的出口。我们只关心u位置是否有数字。
st[u] = 1;
dfs(u+1);
这两句相当于是将这个位置画对勾,然后跳到下一个位置进行选择
st[u]=0;
dfs(u+1);
这两句就是这个位置不填数进入下一轮,顺便回到dfs之前的状态。(这题无所谓)

解法2二进制压缩

1-n的所有整数排列的方案可以看作一个二进制序列,例如1-3的排列中,1 3就对应二进制101。有数字用1表示,没有数字用0表示。
1-n共有2的n次方钟方案。将所有方案数枚举,然后判断位数是否是1。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n;
int main()
{
    scanf("%d",&n);
    for(int i = 0;i < 1<<n;i ++)
    {
        for(int j = 0;j < n;j ++)
        {
            if(i >> j & 1)printf("%d ",j + 1);
        }
        printf("\n");
    }
    return 0;
}

94. 递归实现排列型枚举

这题就是一个全排列问题,和上一题的区别是很明显的。上一个的每个坑位的数字是固定的,可能有或没有,这个题的每个坑位的数是不固定的,且必须有。这个题需要使用st记录是否使用过。这个st和上一个题的st代表的意义不一样。

使用循环来进行dfs。循环从1开始,到n结束。通过st[i]可以知道数字i是否被使用过。如果没被使用过就使用i,然后进入下一层搜索。使用后一定要恢复现场。

image-20240115203650666

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 10;
int m,st[N],ans[N];
int n;
void dfs(int x)
{
    if(x > n) 
    {
       for(int i = 1;i <= n;i ++)
       {
           printf("%d ",ans[i]);
       }
       printf("\n");
    }
 
    for(int i = 1;i <=n;i ++)
    {
        if(!st[i])
        {
            st[i] = 1;
            ans[x] = i;
            dfs(x+1);
            st[i] = 0;
        }
    }
}
int main()
{
    scanf("%d",&n);
    dfs(1);
    return 0;
}

717. 简单斐波那契

image-20240115205913881

使用递推来进行求解,通过观察可以发现这个数列的第n项只与n-1和n-2项有直接关系,所以使用三个变量a b fn,依次向后轮转。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int main(){
    int n,fn;
    scanf("%d",&n);
    int a = 0,b = 1;
    for(int i = 1;i <= n;i ++)
    {
        cout<<a<<" ";
        fn = a+b;
        a=b,b=fn;
    }
}

95. 费解的开关

image-20240115210215243

image-20240115210246482

image-20240115210312290

样例

image-20240115210417313

改变右上角的开关

image-20240115210526298

image-20240115210552593

两步即可让所有的灯变亮。

观察题意可以发现能影响灯本身的除了灯自己还有灯上下左右的灯,可以枚举第一行灯的32种按法,记得备份原数组,然后从第一行按到第四行,第i行可以通过第i+1行的灯来控制,遍历完第四行后,看看第五行还有没有灭的灯,如果有的话,那这个方案就是不可行的。因为没有第六行来控制第五行。如果第五行全亮,那这个就是可以调,判断一下和ans哪个更小。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 6;
char g[N][N],backup[N][N];
int n;
int dx[] = {1,-1,0,0,0};
int dy[] = {0,0,-1,1,0};
void turn(int x,int y){
    for(int i = 0;i < 5;i ++)
    {
        int a = x + dx[i];
        int b = y + dy[i];
        if(a < 0 || b < 0 || a > 4 || b > 4)continue;
        g[a][b] ^= 1;
    }
}
int main(){
    scanf("%d",&n);
    while(n --)
    {
        for(int i = 0;i < 5;i ++)scanf("%s",g[i]);
        int ans = 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)
                {
                    turn(0,i);
                    step ++;
                }
            }
            for(int i = 0;i < 4;i ++)
            {
                for(int j = 0;j < 5;j ++)
                {
                    if(g[i][j] == '0')
                    {
                        turn(i+1,j);
                        step ++;
                    }
                }
            }
            int drak = 0;
            for(int j = 0;j < 5;j ++)
            {
                if(g[4][j] == '0')
                {
                    drak = 1;
                    break;
                }
            }
            if(drak == 0)ans = min(ans,step);
            memcpy(g,backup,sizeof g);
        }
        if(ans > 6)ans = -1;
        cout << ans <<endl;
    }
    return 0;
}

93. 递归实现组合型枚举

image-20240115212247504

image-20240115212301909

这题与全排列的区别就是字典序,只需要在判断是否使用过的时候加上一个判断,条件是当前的i是否大于ans数组的的最后一个元素,大于往里面添加,小于直接就跳过即可。ans数组初始化时要将元素变为-1,否则开头将无法添加。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int N = 26;
int n,m;
int ans[N] = {-1},st[N]={0};
void dfs(int c,int m){
    if(c > m)
    {
        for(int i = 1;i <= m; i ++)
        {
            cout << ans[i] << " ";
        }
        cout<<endl;
        return;
    }
    for(int i = c ;i <= n; i ++)
    {
        if(!st[i]&&i > ans[c-1])
        {
          
          ans[c] = i;
          st[i] = 1;
          dfs(c + 1,m);
          st[i] = 0;
        }
       
    }
}
int main(){
    scanf("%d%d",&n,&m);
    dfs(1,m);
    return 0;
}

1209. 带分数

image-20240115212751409

image-20240115212807361

题意是
n = a + b / c n = a + b/c n=a+b/c
等式两边同时×c
c ∗ n = c ∗ a + b c*n = c*a+b cn=ca+b
通过dfs枚举a和c,然后计算出b,然后遍历st数组看看是否b的每一位都没有被用到。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 30;
int st[N],backup[N];
int n,ans,test;
bool check(int a,int c)
{
    long long b = (long long) n * c -a * c;
    
    if(!a || !b || !c)return false;
   
    memcpy(backup,st,sizeof st);

    while(b)
    {
        int ge = b % 10;
        if(ge == 0 || backup[ge])return false;
        backup[ge] = 1;
        b /= 10;
    }
       
    for(int i = 1;i <= 9;i ++)
    {
        if(backup[i] == 0) return false;
    }
    return true;
}
void dfs_c(int a,int c)
{
    
    if(check(a,c))ans ++;
    for(int i = 1; i <= 9; i ++)
    {
        if(st[i] == 0)
        {
            st[i] = 1;
            dfs_c(a,c*10 + i);
            st[i] = 0;
        }
    }
}
void dfs_a(int a)
{
    
    if(a > n)return;
    if(a)dfs_c(a,0);
    for(int i = 1;i <= 9; i ++)
    {
        if(st[i] == 0)
        {
            st[i] = 1;
            dfs_a(a*10 + i);
            st[i] = 0;
        }
    }
}
int main()
{
    scanf("%d",&n);
    dfs_a(0);
    cout << ans << endl;
    return 0;
}

116. 飞行员兄弟

和费解的开关类似,只不过这个题的数量比较下,所以枚举所有行的全部可能,共65536种,对每一种方案进行操作,记录最少的方案数。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define x first
#define y second
using namespace std;

typedef pair<int,int> PII;
const int N = 5;
char st[N][N],backup[N][N];
vector <PII> ans;
int get(int x,int y)
{
    return x*4 + y;
}
void turn(int x,int y)
{
    if(st[x][y]=='+')st[x][y]='-';
    else st[x][y]='+';
}
void turnall(int x,int y)
{
    for(int i = 0;i < 4;i ++)
    {
        turn(x,i);
        turn(i,y);
    }
    turn(x,y);
}
int main()
{
    for(int i = 0;i < 4;i ++)
    {
        scanf("%s",st[i]);
    }
    for(int i = 0;i < 1 << 16;i ++)
    {
        vector <PII> step;
        memcpy(backup,st,sizeof st);
        for(int x = 0;x < 4;x ++)
        {
            for(int y = 0;y < 4;y ++)
            {
                if(i >> get(x,y) & 1)
                {
                    turnall(x,y);
                    step.push_back({x,y});
                }
            }
        }
        int dark = 0;
        for(int x = 0;x < 4;x ++)
        {
            for(int y = 0;y < 4;y ++)
            {
                if(st[x][y]=='+')
                {
                   dark = 1;
                   break;
                }
            }
        }
        if(dark == 0)
        {
            if(ans.empty()||ans.size() > step.size()) ans = step;
        }
         memcpy(st,backup,sizeof st);
    }
    
    cout << ans.size() << endl;
    for(auto p:ans)
    {
        cout << p.x+1<<" "<<p.y+1<<endl;
    }
    return 0;
}

1208. 翻硬币

有个初始态有个结束态。将初始态与结束态一一对比,遇到不一样的就将移动次数加一并且变换硬币状态。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int ans;
string start,aim;
void turn(int i)
{
    if(start[i]=='*')start[i] = 'o';
    else start[i] = '*';
}
int main()
{
    cin>>start>>aim;
    for(int i = 0;i < start.size() - 1;i ++)
    {
        if(start[i]!=aim[i])turn(i+1),ans++;
        
    }
    cout << ans <<endl;
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1396247.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Pytest插件pytest-django让Django测试更高效

在Django应用开发中&#xff0c;测试是确保应用质量的关键环节。然而&#xff0c;Django自带的测试框架并非总能满足开发者的需求&#xff0c;而Pytest插件 pytest-django 则为我们提供了更为灵活、强大的测试工具。本文将深入介绍 pytest-django 插件的基本用法和实际案例&…

【springboot】配置文件入门

配置文件入门 配置文件最重要的目的&#xff1a;解决硬编码问题(代码写死) 我们接下来主要介绍两个方面&#xff1a;常见的配置项和配置文件的使用 SpringBoot 的配置文件,有三种格式 propertiesyamlyml(yaml的简写) 用的较多的是yml和properties文件 如果项目中,同时存在…

常用中间件漏洞

IIS6 IIS7 安装 控制面板-----打开关闭windows功能 添加角色-----添加IIS 启动之后访问localhost 复现 服务器换成IIS7 访问报错 大概就是缺少CGI模块 问题解决 添加php-cgi的路径 添加脚本映射 修改php.ini文件 将 cgi.fix_pathinfo1 然后设置一个图片 访问 在后缀加上/.…

情人节专属--HTML制作情人节告白爱心

💕效果展示 💕html展示 <!DOCTYPE html> <html lang="en" > <head>

C#: form 窗体的各种操作

说明&#xff1a;记录 C# form 窗体的各种操作 1. C# form 窗体居中显示 // 获取屏幕的宽度和高度 int screenWidth Screen.PrimaryScreen.Bounds.Width; int screenHeight Screen.PrimaryScreen.Bounds.Height;// 设置窗体的位置 this.StartPosition FormStartPosition.M…

vue基于Spring Boot共享单车租赁报修信息系统

共享单车信息系统分为二个部分&#xff0c;即管理员和用户。该系统是根据用户的实际需求开发的&#xff0c;贴近生活。从管理员处获得的指定账号和密码可用于进入系统和使用相关的系统应用程序。管理员拥有最大的权限&#xff0c;其次是用户。管理员一般负责整个系统的运行维护…

Byrdhouse AI实时语音翻译工具,可以在视频通话中翻译100多种语言

你是否曾经在跨国会议或与外国友人聊天时&#xff0c;因为语言不通而感到尴尬或困扰&#xff1f;是不是还在找可以实时翻译的软件或者APP&#xff1f;现在&#xff0c;有了这款语音翻译神器&#xff0c;一切都将变得简单&#xff01; 免费使用链接&#xff1a;https://byrdhous…

JVM性能调优-垃圾收集器ZGC详解

1. ZGC收集器(-XX:UseZGC) 参考文章&#xff1a;Main - Main - OpenJDK Wiki http://cr.openjdk.java.net/~pliden/slides/ZGC-Jfokus-2018.pdf ZGC是一款JDK 11中新加入的具有实验性质的低延迟垃圾收集器&#xff0c;ZGC可以说源自于是Azul System公司开发的C4&#xff08;…

必学!白银现货排期基础知识

白银现货排期是一种交易模式&#xff0c;它涉及到未来交货的安排。在这种模式之下&#xff0c;买卖双方可以预先达成协议&#xff0c;确定未来某一时间的交货安排。现货排期这种交易方式的特点&#xff0c;是白银会在约定的时间交付&#xff0c;而价格可以在合约签订时确定。 白…

计算机网络——数据链路层(1)

一、概述 在计算机网络中&#xff0c;数据链路层承担着点对点通信的任务&#xff0c;用于跨物理层在网段节点之间参数数据。它在网络分层中处于物理层之上&#xff0c;网路层之下。 在链路层的讨论中&#xff0c;我们将看到两种截然不同类型的链路层信道。第一种类型是广播信道…

WAF攻防相关知识点总结1--信息收集中的WAF触发及解决方案

什么是WAF WAF可以通过对Web应用程序的流量进行过滤和监控&#xff0c;识别并阻止潜在的安全威胁。WAF可以检测Web应用程序中的各种攻击&#xff0c;例如SQL注入、跨站点脚本攻击&#xff08;XSS&#xff09;、跨站请求伪造&#xff08;CSRF&#xff09;等&#xff0c;并采取相…

python如何包含其他路径的模块

python 包含其他路径的模块&#xff1a; 例如目录结构: dir1 |__ init.py |__ module1.py dir2 |__ main.py main.py from dir1 import module1首先需要在 dir1 添加 init.py 文件&#xff0c;该文件可以是空文件。 其次需要将dir1 的父目录添加到python 解释器的&#xf…

Js-WebAPIs-事件(二)

事件监听&#xff08;绑定&#xff09; 什么是事件&#xff1f; 事件是在编程时系统内发生的动作或者发生的事情 比如用户在网页上单击一个按钮 什么是事件监听&#xff1f; 就是让程序检测是否有事件产生&#xff0c;一旦有事件触发&#xff0c;就立即调用一个函数做出响…

springboot 原理分析之自动配置

一、Condition Condition 是在 Spring 4.0 增加的条件判断功能&#xff0c;通过这个可以功能可以实现选择性的创建 Bean 操作。比如说&#xff0c;只有满足某一个条件才能创建这个 Bean&#xff0c;否则就不创建。 SpringBoot 是如何知道要创建哪个 Bean 的&#xff1f;比如 Sp…

一文说明白 MySQL 的 ACID 和 几种日志的关系

1、简介 我们对于MySQL 很熟悉&#xff0c;关于其特性都有一定的了解&#xff0c;但是关于一些具体的实现原理&#xff0c;有的小伙伴可能不太熟悉&#xff0c;而且这部分知识在我们互联网大厂面试中是经常涉及的&#xff0c;因此&#xff0c;本文将带你深入底层&#xff0c;顺…

【计算机网络】子网划分(经典基础练习题)

一、某主机IP地址为110.35.2.68&#xff0c;子网掩码为255.255.255.128&#xff0c;求网络地址&#xff1f; 二、有A类网络18.0.0.0的子网掩码为255.128.0.0&#xff0c;请问可以划分为多少个子网&#xff1f; 并写出每个子网的子网号&#xff1f; 三、将C类网119.181.25.0划分…

Docker容器添加映射端口

方式一 简单粗暴&#xff08;需要等一段时间&#xff09; 直接给现在容器停了&#xff08;当然你要不想停也可以&#xff0c;只是打包会慢一点&#xff0c;当然我是没出意外&#xff0c;如果你怕出现特殊情况&#xff0c;那就先把容器停了&#xff09;&#xff0c;然后把这个容…

SSL证书自动化管理有什么好处?如何实现SSL证书自动化?

SSL证书是用于加密网站与用户之间传输数据的关键元素&#xff0c;在维护网络安全方面&#xff0c;管理SSL证书与部署SSL证书一样重要。定期更新、监测和更换SSL证书&#xff0c;可以确保网站的安全性和合规性。而自动化管理可以为此节省时间&#xff0c;并避免人为错误和不必要…

Oracle命令大全

文章目录 1. SQL*Plus命令&#xff08;用于连接与管理Oracle数据库&#xff09;2. SQL数据定义语言&#xff08;DDL&#xff09;命令3. SQL数据操作语言&#xff08;DML&#xff09;命令4. PL/SQL程序块5. 系统用户管理6. 数据备份与恢复相关命令1. SQL*Plus命令&#xff08;用…

App开发——国际化多语言的实现

1.引言 我们当前正处于一个全球化的世界&#xff0c;所以我们开发的 App 也会有很大的概率&#xff0c;需要满足国际化多语言的需求。今天刚好看到有个小伙伴遇到了这个需求需要实现&#xff0c;这里就借此机会&#xff0c;简单讲解一下&#xff0c;在 YonBuilder移动开发 技术…