蓝桥杯省赛专题训练之递归与递推训练(相关真题和模板题)

题目:92. 递归实现指数型枚举

在这里插入图片描述

题解:递归。注意不存在的空行也是需要输出的,否则报错。
方法一:

#include<bits/stdc++.h>

using namespace std;
typedef long long LL;
typedef pair<double,double>PII;
const int N=1e5+10;
const int mod=1000000009;
int n;
int a[20];
void dfs(int u,int ct){
    if(u>n){
        for(int i=1;i<=ct;i++){
            printf("%d ",a[i]);
        }
        puts("");
        return;
    }
    //不选
    dfs(u+1,ct);
    a[ct+1]=u;//选
    dfs(u+1,ct+1);

}
int main(){
    cin>>n;
    dfs(1,0);
    return 0;
}

方法二:

#include<bits/stdc++.h>

using namespace std;
typedef long long LL;
typedef pair<double,double>PII;
const int N=1e5+10;
const int mod=1000000009;
int n;
bool a[20];
void dfs(int u){
    if(u>n){
        for(int i=1;i<=n;i++){
            if(a[i]) printf("%d ",i);
        }
        puts("");
        return;
    }
    a[u]=1;
    dfs(u+1);
    a[u]=0;
    dfs(u+1);

}
int main(){
    cin>>n;
    dfs(1);
    return 0;
}

题目:94. 递归实现排列型枚举

在这里插入图片描述
题解:递归
方法一:递归写法。

#include<bits/stdc++.h>

using namespace std;
typedef long long LL;
typedef pair<double,double>PII;
const int N=1e5+10;
const int mod=1000000009;
int n;
bool sta[10];
int a[10];
void dfs(int ct){
    if(ct==n){
        for(int i=0;i<n;i++){
            printf("%d ",a[i]);
        }
        puts("");
        return;
    }
    for(int i=1;i<=n;i++){
        if(!sta[i]){
            sta[i]=1;
            a[ct]=i;
            dfs(ct+1);
            sta[i]=0;
        }
    }
}
int main(){
    cin>>n;
    dfs(0);
    return 0;
}

方法二:用的是next_permutation(a+1,a+1+n)函数

#include<bits/stdc++.h>

using namespace std;
typedef long long LL;
typedef pair<double,double>PII;
const int N=1e5+10;
const int mod=1000000009;
int n;
bool sta[10];
int a[10];

int main(){
    cin>>n;
    for(int i=1;i<=n;i++)
        a[i]=i;
    do{
        for(int i=1;i<=n;i++){
            printf("%d ",a[i]);
            
        }
        puts("");
    }while(next_permutation(a+1,a+1+n));
    return 0;
}

题目:717. 简单斐波那契

在这里插入图片描述
题解:循环结构+递推

#include<bits/stdc++.h>

using namespace std;
typedef long long LL;
typedef pair<double,double>PII;
const int N=1e5+10;
const int mod=1000000009;
int n;
LL a[50]={0,1};

int main(){
    cin>>n;
    for(int i=2;i<n;i++){
        a[i]=a[i-1]+a[i-2];
    }
    for(int i=0;i<n;i++){
        printf("%lld ",a[i]);
    }
    return 0;
}

题目:95. 费解的开关

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
题解:递推+位运算

#include<bits/stdc++.h>

using namespace std;
typedef long long LL;
typedef pair<double,double>PII;
const int N=1e5+10;
const int mod=1000000009;
int t;
char a[10][10],b[10][10];
int fx[5]={0,0,0,1,-1};
int fy[5]={0,1,-1,0,0};
void turn_all(int x,int y){
    for(int i=0;i<5;i++){
        int xx=x+fx[i];
        int yy=y+fy[i];
        if(xx<1||xx>5||yy<1||yy>5) continue;
        if(a[xx][yy]=='0') a[xx][yy]='1';
        else a[xx][yy]='0';
    }
}
int main(){
    cin>>t;
    getchar();
    while(t--){
        for(int i=1;i<=5;i++)
            scanf("%s",a[i]+1);
//        for(int i=1;i<=5;i++){
//            for(int j=1;j<=5;j++){
//                printf("%c",a[i][j]);
//            }
//            puts("");
//        }
        int ans=10;
        memcpy(b,a,sizeof a);
        for(int i=0;i<(1<<5);i++){
            memcpy(a,b,sizeof b);
            int res=0;
            for(int j=0;j<5;j++){
                if(i>>j&1){
                    res++;
                    turn_all(1,j+1);
                }
            }
            bool flag=1;
            for(int j=1;j<5;j++){
                for(int k=1;k<=5;k++){
                    if(a[j][k]=='0'){
                        res++;
                        if(res>6){
                            flag=0;
                            res=10;
                            break;
                        }
                        turn_all(j+1,k);
                    }
                }
                if(flag==0) break;
            }

            for(int j=1;j<=5;j++){
                if(a[5][j]=='0'){
                    flag=0;
                    res=10;
                    break;
                }
            }
            if(flag){
                ans=min(ans,res);
            }
        }
        if(ans<=6) printf("%d\n",ans);
        else cout<<"-1"<<endl;
    }
    return 0;
}

题目:93. 递归实现组合型枚举

在这里插入图片描述
题解:递归+dfs。因为是从n个里面随便抽取m个,所以需要有两个参数,而像那种求的是n个数的全排列,只需要一个参数去记录已选的数量即可。

#include<bits/stdc++.h>

using namespace std;
typedef long long LL;
typedef pair<double,double>PII;
const int N=1e5+10;
const int mod=1000000009;
int a[30];
int n,m;
void dfs(int u,int ct){
    if(ct==m){
        for(int i=0;i<ct;i++){
            printf("%d ",a[i]);
        }
        puts("");
        return;
    }
    if(u>n) return;
    a[ct]=u;
    dfs(u+1,ct+1);
    dfs(u+1,ct);
}
int main(){
    cin>>n>>m;
    dfs(1,0);
    return 0;
}

题目:1209. 带分数

在这里插入图片描述
题解:用next_permutation(a+1,a+1+9),对1-9进行全排列,然后再在里面用两层循环进行枚举,寻找符合要求的数。(注意,一般有除法的都建议转换为乘法)

#include<bits/stdc++.h>

using namespace std;
typedef long long LL;
typedef pair<double,double>PII;
const int N=1e5+10;
const int mod=1000000009;
int a[15];
int main(){
    int n;
    cin>>n;
    for(int i=1;i<=9;i++)
        a[i]=i;
    LL ans=0;
    do{
        for(int i=1;i<=7;i++){
            for(int j=i+1;j<=8;j++){
                int a1=a[1];
                int idx=1;
                while(idx<i){
                    a1=a1*10+a[idx+1];
                    idx++;
                }
                int a2=a[i+1];
                idx=i+1;
                while(idx<j){
                    a2=a2*10+a[idx+1];
                    idx++;
                }
                int a3=a[j+1];
                idx=j+1;
                while(idx<9){
                    a3=a3*10+a[idx+1];
                    idx++;
                }
                if(n*a3==(a1*a3+a2)) ans++;
            }
        }
    }while(next_permutation(a+1,a+1+9));
    printf("%lld",ans);
    return 0;
}

题目:116. 飞行员兄弟

在这里插入图片描述
在这里插入图片描述
题解:枚举+位运算

#include<bits/stdc++.h>

using namespace std;
typedef long long LL;
typedef pair<double,double>PII;
const int N=1e5+10;
const int mod=1000000009;
char a[5][5],b[5][5];
void turn_one(int x,int y){
    if(a[x][y]=='+') a[x][y]='-';
    else a[x][y]='+';
}
void turn_all(int x,int y){
    for(int i=0;i<4;i++){
        turn_one(x,i);
    }
    for(int i=0;i<4;i++){
        turn_one(i,y);
    }
    turn_one(x,y);
}
int main(){
    for(int i=0;i<4;i++)
        scanf("%s",a[i]);
//    for(int i=0;i<4;i++){
//        for(int j=0;j<4;j++){
//            cout<<a[i][j]<<" ";
//        }
//        cout<<endl;
//    }

    int minn=30,res=0;
    memcpy(b,a,sizeof a);
    for(int i=0;i<(1<<16);i++){
        memcpy(a,b,sizeof b);
        //int t=i;
        int ans=0;
        bool flag=1;
        for(int j=0;j<16;j++){
            if(i>>j&1){
                ans++;
                if(ans>minn){
                    flag=0;
                    break;
                    ans=30;
                }
                turn_all(j/4,j%4);//注意这里是j不是i
            }
        }
        
        for(int j=0;j<4;j++){
            for(int k=0;k<4;k++){
                if(a[j][k]=='+'){
                    flag=0;
                    ans=40;
                    break;
                }
            }
        }
        //cout<<endl<<ans;
        if(flag){
            if(minn>ans){
                minn=ans;
                res=i;
            }
        }
    }
    if(minn<30){
        cout<<minn<<endl;
        for(int i=0;i<16;i++){
            if(res>>i&1){
                cout<<i/4+1<<" "<<i%4+1<<endl;
            }
        }
    }
    return 0;
}

题目:1208. 翻硬币

在这里插入图片描述
在这里插入图片描述
题解:假定每次翻动第i枚硬币时,i+1也翻动。那么我们只需要从第一位开始来判断a[i]与b[i]是否相同,不相同就翻转,并且改变下一位,这就是贪心的最优解

#include<bits/stdc++.h>

using namespace std;
typedef long long LL;
typedef pair<double,double>PII;
const int N=1e5+10;
const int mod=1000000009;
char a[110],b[110];
int main(){
    cin>>a;
    cin>>b;
    int lena=strlen(a);
    int ans=0;
    for(int i=0;i<lena-1;i++){
        if(a[i]!=b[i]){
            ans++;
            if(a[i+1]=='*') a[i+1]='o';
            else a[i+1]='*';
        }
    }
    cout<<ans;
    return 0;
}

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值