zoukankan      html  css  js  c++  java
  • [递归专题打卡]2021 6.30-7.2

    ​同步于本人CSDN   https://blog.csdn.net/qq_39391544

    2021/6/30

    链接:https://ac.nowcoder.com/acm/problem/14310
    来源:牛客网
     

    ★字符串逆序

    输入一个字符串,长度在100以内,按相反次序输出其中的所有字符。

    输入描述:

    输入一个字符串

    输出描述:

    输出反序的字符串

    示例1

    输入

    tsinghua

    输出

    auhgnist

    解答:

     1 #include<stdio.h>
     2 #include<string.h>
     3 int lenth;
     4 void Output(char* a,int n)
     5 {
     6     if(n==lenth)
     7         return;
     8     Output(a,n+1);
     9     printf("%c",a[n]);
    10 }
    11 int main()
    12 {
    13     char a[101];
    14     scanf("%s",a);
    15     lenth=strlen(a);
    16     Output(a,0);
    17     return 0;
    18 }

     

     

    链接:https://ac.nowcoder.com/acm/problem/14320
    来源:牛客网
     

    ★杨辉三角

    杨辉三角形又称Pascal三角形,它的第i+1行是(a+b)i的展开式的系数。

    它的一个重要性质是:三角形中的每个数字等于它两肩上的数字相加。

    下面给出了杨辉三角形的前4行:

       1

      1 1

     1 2 1

    1 3 3 1

    给出n,输出它的前n行。

    输入描述:

    输入包含一个数n。

    输出描述:

    输出杨辉三角形的前n行。每一行从这一行的第一个数开始依次输出,中间使用一个空格分隔。请不要在前面和后面输出多余的空格。

    示例1

    输入

    4

    输出

    1
    1 1
    1 2 1
    1 3 3 1

    说明

    1 <= n <= 34。

    解答:

     1 #include<iostream>
     2 #define Maxn 100000
     3 using namespace std;
     4 
     5 int N;
     6 int a[Maxn];
     7 void Output(int n)
     8 {
     9     if(n==N+1)
    10         return ;
    11     a[n]=1;
    12 //    for(int j=2;j<n;j++){
    13 //        a[j]=a[j-1]+a[j];
    14 //    }//与倒序循环有微妙差距 
    15     for(int j=n-1;j>=2;j--){
    16         a[j]=a[j-1]+a[j];
    17     }
    18     for(int j=1;j<=n;j++){
    19         if(j==1){
    20             cout<<a[j];
    21         }else{
    22             cout<<' '<<a[j];
    23         }
    24     }
    25     cout<<endl;
    26     Output(n+1);    
    27 }
    28 int main()
    29 {
    30     a[1]=1;
    31     cin>>N;
    32     Output(1);
    33     return 0;
    34 }

     

     

    链接:https://ac.nowcoder.com/acm/problem/14356
    来源:牛客网
     

    ★s01串

    s01串初始为"0"
    按以下方式变换
    0变1,1变01

    输入描述:

    1个整数(0~19)

    输出描述:

    n次变换后s01串

    示例1

    输入

    3

    输出

    101

    说明

    初始为0 第一次变化后为 1  第二次变化后为 01  第三次变化后为 101

    备注:

    数据规模和约定
    0~19
    

    解答:

     1 #include<iostream>
     2 using namespace std;
     3 
     4 string Output(int n)
     5 {
     6     if(n==0) return "0";
     7     if(n==1) return "1";
     8     return Output(n-2)+Output(n-1);
     9 }
    10 int main()
    11 {
    12     int N;
    13     cin>>N;
    14     cout<<Output(N);
    15     return 0;
    16 }

     

    2021/7/1

    链接:https://ac.nowcoder.com/acm/problem/14703
    来源:牛客网
     

    ★★素数回文

    现在给出一个素数,这个素数满足两点:

    1、  只由1-9组成,并且每个数只出现一次,如13,23,1289。

    2、  位数从高到低为递减或递增,如2459,87631。

    请你判断一下,这个素数的回文数是否为素数(13的回文数是131,127的回文数是12721)。

    输入描述:

    输入只有1行。

    第1行输入一个整数t,保证t为素数。

    数据保证:9<t<109

    输出描述:

    输出一行字符串,如果t的回文数仍是素数,则输出“prime”,否则输出"noprime"。

    示例1

    输入

    13

    输出

    prime

    说明

    13的回文数是131,131是素数

    示例2

    输入

    17

    输出

    noprime

    说明

    17的回文数是171,171不是素数(因子有3)

    备注:

    素数定义为在大于1的自然数中,除了1和它本身以外不再有其他因数。
    素数的回文数为题意中的定义,1331不是素数的回文数。

     

    解答:

    #include<iostream>
    using namespace std;
    
    bool Isprime(long long number)
    {
        if(number<2) return false;
        for(int i=2; i<=number/i; i++)
        {
            if(number%i==0)
                return false;
        }
        return true;
    }
    int main()
    {
        char num[10];    
        long long a,b,c;
        cin>>a;
        for(c=a/10; c!=0; c/=10)
        {
            a*=10;
            a+=c%10;
        }
        
        if(Isprime(a))
            cout<<"prime";
        else
            cout<<"noprime";
        
        return 0;
    }

     

      链接:https://ac.nowcoder.com/acm/problem/14582
    来源:牛客网

     


    ★★★LP钱不够

    吃货LP参加了珠海美食节,每见一家摊位都会大吃一顿,但是如果不加收敛,接下来的日子就只能吃土了,所以,他决定只向前,不回头,花最少的钱,在美食节上吃出一条血路。在美食节的矩形地图中,LP站在左上角的入口,请帮助Ta到达右下角的出口。

    输入描述:

    第一行包含一个正整数T(T<=10),表示有T组测试数据。
    每组数据第一行包含一个正整数n(3 <= n<=20)。
    给定一个n*n矩阵图,从左上角开始每次只能向右或者向下走,最后到达右下角的位置,路径上所有的数字累加起来就是花费和,返回所有路径中最小的花费和。
    无摊位时花费为0,不会有负花费。

    输出描述:

    对于每一组数据,有一行输出,返回最小花费,最后输出无换行。

    示例1

    输入

    1
    5
    25 81 51 98 43 
    19 10 36 81 91 
    95 38 7 84 40 
    87 27 72 9 30 
    33 81 68 21 71

    输出

    270

     

    解答:

     

    #include<iostream>
    using namespace std;
    
    int main()
    {
        int num[21][21]={0};
        int N,x;
        cin>>N;
        while(N--){
            cin>>x;
            for(int i=1; i<=x; i++)
            {
                for(int j=1; j<=x; j++)
                    cin>>num[i][j];
            }
            
            for(int m=x;m>=1;){
                for(int n=x-1;m>=1;){
                    for(int i=m,j=n;i>=m,j<=m;i--,j++){    
                            //cout<<"("<<i<<','<<j<<") "; 
                            if(i==x){
                                num[i][j]+=num[i][j+1];
                            }else if(j==x){
                                num[i][j]+=num[i+1][j];
                            }else{
                                num[i][j]+=min(num[i+1][j],num[i][j+1]);//保证每一个子问题的最优解
                            }    
                    }
                    //cout<<"("<<m<<','<<n<<") "; 
                    if(n==1){
                        m--;
                    }else{
                        n--;
                    }
                }
            }
            cout<<num[1][1]<<endl;    
        }
        return 0;
    }

     

    这是一道数塔问题的变种,核心思想是相同的,即运用动态规划的思想,把一个复杂的问题划分成无数个子问题,保证每一个子问题的最优解,通过拆分问题,定义问题状态和状态之间的关系,使得问题能够以递推(或者说分治)的方式去解决.得到全局最优解

     

    此题比起简单的数塔,难在DP的顺序,例如下图矩阵大小为4*4时:


     

     

     

    而每一层的起始点循环的方向则是按照红线的顺序(不唯一)

     

     

    补充:

    数塔
    在讲述DP算法的时候,一个经典的例子就是数塔问题,它是这样描述的:

    有如下所示的数塔,要求从顶层走到底层,若每一步只能走到相邻的结点,则经过的结点的数字之和最大是多少?


    已经告诉你了,这是个DP的题目,你能AC吗?
    Input
    输入数据首先包括一个整数C,表示测试实例的个数,每个测试实例的第一行是一个整数N(1 <= N <= 100),表示数塔的高度,接下来用N行数字表示数塔,其中第i行有个i个整数,且所有的整数均在区间[0,99]内。
    Output
    对于每个测试实例,输出可能得到的最大和,每个实例的输出占一行。
    Sample Input
    1
    5
    7
    3 8
    8 1 0
    2 7 4 4
    4 5 2 6 5
    Sample Output
    30

    #include<iostream>
    #include<cstdio>
    using namespace std;
    
    int N;
    int a[10000],book[10000];
    
    void dfs(int step)
    {
        if(step==N+1)
        {
            for(int i=1; i<=N; i++)
            {
                printf("%5d",a[i]);
                //cout<<a[i]<<' ';
            } 
            cout<<endl;
            return ;
        }
        for(int i=1; i<=N; i++)
        {
            if(book[i]==0)
            {
                a[step]=i; 
                book[i]=1;
                dfs(step+1);
                book[i]=0;
            } 
        } 
        return ;
    }
    int main()
    {    
        cin>>N;
        for(int i=1;i<=N;i++)
        {
            a[i]=i;
            book[i]=0;
        }
        dfs(1);
    
        return 0;
    }
     

     

     

     

    链接:https://ac.nowcoder.com/acm/problem/14839
    来源:牛客网
     

     

    ★最大公约数

    输入两个数,求最大公约数。

    输入描述:

    输入两个数a,b.

    输出描述:

    输出a和b的最大公约数

    示例1

    输入

    6
    3

    输出

    3

    解答:

    #include<iostream>
    using namespace std;
    
    int gcd(int a,int b){
        if(b==0) return a;
        return gcd(b,a%b); 
    }
    int main()
    {
        int a,b;
        cin>>a>>b;
        cout<<gcd(a,b);
        return 0;
    }

     

    2021/7/2

    链接:https://ac.nowcoder.com/acm/problem/14359
    来源:牛客网
     

    ★Fibonacci数列

    Fibonacci数列的递推公式为:Fn=Fn-1+Fn-2,其中F1=F2=1。

    当n比较大时,Fn也非常大,现在我们想知道,Fn除以10007的余数是多少。

    输入描述:

    输入包含一个整数n。

    输出描述:

    输出一行,包含一个整数,表示Fn除以10007的余数。

    示例1

    输入

    10

    输出

    55

    示例2

    输入

    22

    输出

    7704

    备注:

    
    

    说明:在本题中,答案是要求Fn除以10007的余数,因此我们只要能算出这个余数即可,而不需要先计算出Fn的准确值,再将计算的结果除以10007取余数,直接计算余数往往比先算出原数再取余简单。

    数据规模与约定

    1 <= n <= 1,000,000。

    解答:

    #include<iostream>
    using namespace std;
    
    int main()
    {
        int n;
        int num[3]={1,1,0};
        cin>>n;
        
        if(n==1||n==2){
            cout<<"1"; 
        }else{
            for(int i=3; i<=n; i++)
            {
                num[2]=(num[0]+num[1])%10007;
                num[0]=num[1];
                num[1]=num[2];
            }
            cout<<num[2];
        } 
        return 0;
    }

     

     1.全排列

    例题:洛谷P1706 全排列问题

    题目描述

    输出自然数 1 到 n 所有不重复的排列,即 nn 的全排列,要求所产生的任一数字序列中不允许出现重复的数字。

    输入格式

    一个整数 n。

    输出格式

    由 1∼n 组成的所有不重复的数字序列,每行一个序列。

    每个数字保留 5 个场宽。

    输入输出样例

    输入

    3

    输出 

        1    2    3
        1    3    2
        2    1    3
        2    3    1
        3    1    2
        3    2    1
    

    说明/提示

    1≤n≤9

    解答:

    #include<iostream>
    #include<cstdio>
    using namespace std;
    
    int N;
    int a[10000],book[10000];
    
    void dfs(int step)
    {
        if(step==N+1)
        {
            for(int i=1; i<=N; i++)
            {
                printf("%5d",a[i]);
                //cout<<a[i]<<' ';
            } 
            cout<<endl;
            return ;
        }
        for(int i=1; i<=N; i++)
        {
            if(book[i]==0)
            {
                a[step]=i; 
                book[i]=1;
                dfs(step+1);
                book[i]=0;
            } 
        } 
        return ;
    }
    int main()
    {    
        cin>>N;
        for(int i=1;i<=N;i++)
        {
            a[i]=i;
            book[i]=0;
        }
        dfs(1);
    
        return 0;
    }

    模板:

    void dfs(int step)
    {
        判断边界{
            ...// 输出
            返回 
        } 
        尝试每一种可能{
            判断状态{
                ...
                继续下一步 dfs(step+1) 
                ...//初始化执行这一步前所改变的状态
            }  
        } 
        返回 
    }

    2.所有组合

    例题:洛谷P1157 组合的输出

    题目描述

    排列与组合是常用的数学方法,其中组合就是从n个元素中抽出rr个元素(不分顺序且r≤n),我们可以简单地将n个元素理解为自然数1,2,…,n,从中任取r个数。

    现要求你输出所有组合。

    例如n=5,r=3,所有组合为:

    12 3 , 1 2 4 , 1 2 5 , 1 3 4 ,1 3 5 , 1 4 5 , 2 3 4 , 2 3 5 , 2 4 5 , 3 4 5

    输入格式

    一行两个自然数n,r(1<n<21,0≤r≤n)。

    输出格式

    所有的组合,每一个组合占一行且其中的元素按由小到大的顺序排列,每个元素占三个字符的位置,所有的组合也按字典顺序。

    注意输出时,每个数字需3个场宽,pascal可以这样:

    write(ans:3);

    输入输出样例

    输入 

    5 3 
    

    输出

      1  2  3
      1  2  4
      1  2  5
      1  3  4
      1  3  5
      1  4  5
      2  3  4
      2  3  5
      2  4  5
      3  4  5

    解答:

    #include<iostream>
    #include<cstdio>
    using namespace std;
    
    int n,r;
    int a[10000];
    
    void dfs(int m)
    {
        if(a[0]==r)
        {
            for(int i=1; i<=r; i++)
            {
                printf("%3d",a[i]);
                //cout<<a[i]<<' ';
            } 
            cout<<endl;
            return ;
        }
        for(int i=m; i<=n; i++)
        {
            a[++a[0]]=i;
            dfs(i+1);
            a[a[0]--]=0;
        } 
    }
    int main()
    {    
        cin>>n>>r;
        dfs(1);
        return 0;
    }



    天涯犹在,不诉薄凉。
  • 相关阅读:
    320 Generalized Abbreviation
    319. Bulb Switcher
    三条用人原则
    Go 编码问题的解决方案
    C# MVC js 跨域
    apidoc接口文档的快速生成
    go语言学习
    C#系统之垃圾回收
    WCF项目启动时错误处理
    XML之XPath
  • 原文地址:https://www.cnblogs.com/Knight02/p/14965724.html
Copyright © 2011-2022 走看看