练习3

问题 A: 递归求解


时间限制: 5 Sec  内存限制: 128 MB



提交: 6  解决: 2  201501010119


提交状态讨论版 
  



题目描述 

使用递归编写一个程序,求如下数列的前n项: 

s=112 +1314 +1516 +....+1n  
s=112+1314+1516+....+1n
    


输入 

多组数据输入,每组输入一个正整数n 



输出 

输出前n项的结果(精确到小数点后六位) 



样例输入 Copy 

1



样例输出 Copy 

1.000000
#include <bits/stdc++.h>
 
using namespace std;
 
double f(int n)
{
    if(n==1)
        return 1;
    else
        if(n%2==0)
        {
            return f(n-1.0)-1.0/n;
        }
        else
            if(n%2!=0)
        {
            return f(n-1)+1.0/n;
        }
}
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
    printf("%.6f\n",f(n));
    }
    return 0;
}

 

问题 D: 数的划分


时间限制: 1 Sec  内存限制: 128 MB



提交: 0  解决: 0  201501010119


提交状态讨论版 
  



题目描述 

使用递归编写一个程序,求一个正整数n的全部划分个数。 
 例如,输入3,输出3;输入4,输出5。 




输入 

多组输入,每一组是一个正整数n。 



输出 

输出划分数。 



样例输入 Copy 

3
4




样例输出 Copy 

3
5

感受这个题和分苹果有点相似(前面写过);c++

 

f(3)=3,f(4)=5,f(6)=11;算法

题目意思:将一个正整数划分为几个正整数;数组

3的分法:3;2+1;1+1+1函数

4的分法:4;2+2;1+3;1+2+1;1+1+1+1测试

6的分法:6;1+5;4+2;4+1+1;3+3;3+2+1;3+1+1+1;2+2+2;2+2+1+1;2+1+1+1+1;1+1+1+1+1+1spa

设n,m;将n分解成不大于m的数设为:f(n,m),意思是:举个栗子,f(6,3),将6分红不大于3的数的分法,这样分:3,3; 3,2,1; 3,1,1,1;.net

这样看来,f(6,3)的分法能够由n-m的数(称为剩下的数)有几种分法;设计

因此f(6,3)由两种分法组成,第一种是f(3,3)组成(被减掉的最大数),第二种是被减掉剩下的数的划分方法,也就是f(6,2);code

这个就是咱们的通常规律;blog

 

如今来讨论特殊状况:

f(n,1)=1,n>=1; 将n分解成n个1,只有一种分法;

f(n,m),n<m, 其实就等于f(n,n);  因此f(1,m)=1;

f(n,n)=f(n,n-1)+1(本身等于本身的状况,举个栗子:6分红6); f(n,n-1)又能够递归到f(n,m)的通常状况;

 

#include <bits/stdc++.h>
 
using namespace std;
 
int q(int n,int m)
{
    if((n<1)||(m<1))
    {
        return 0;
    }
 
    if((n==1)||(m==1))
    {
        return 1;
    }
 
    if(n<m)
        return q(n,n);
    if(n==m)
        return q(n,m-1)+1;
    else
        return q(n,m-1)+q(n-m,m);
}
 
int main()
{
    int n;
    while(cin>>n)
    {
        q(n,n);  //输入状况是这样子
        cout<<q(n,n)<<endl;
    }
    return 0;
}

 

          感受这题的难点就是要想到如何分解整数,按照哪几个条件来分;

大概递归树就是这样子的吧~

 

 

问题 E: 汉诺塔


时间限制: 1 Sec  内存限制: 128 MB



提交: 0  解决: 0  201501010119


提交状态讨论版 
  



题目描述 


使用递归编写一个程序实现汉诺塔问题,要求在输入圆盘数量以后,输出圆盘的移动步骤,输出格式示例以下: 


第1步:1号盘从A柱移至B柱 
第2步:2号盘从A柱移至C柱 






输入 

多组测试用例,每组输入一个正整数n,n表明圆盘数量。    



输出 

每组输出之间有一行空行。
 




样例输入 Copy 

3



样例输出 Copy 

第1步:1号盘从A柱移至C柱
第2步:2号盘从A柱移至B柱
第3步:1号盘从C柱移至B柱
第4步:3号盘从A柱移至C柱
第5步:1号盘从B柱移至A柱
第6步:2号盘从B柱移至C柱
第7步:1号盘从A柱移至C柱
#include <bits/stdc++.h>
 
using namespace std;
 
int s=0;
 
void move(int n,char a,char b)
{
    printf("第%d步:%d号盘从%c柱移至%c柱\n",++s,n,a,b);
}
 
void hano(int n,char a,char b,char c)  //从a移到c借助b
{
    if(n==1)
        {
            move(1,a,c);
        }
    else
    {
        hano(n-1,a,c,b);
        move(n,a,c);
        hano(n-1,b,a,c);
    }
}
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        s=0;
        hano(n,'A','B','C');   //注意ABC要打单引号
        cout<<endl;
    }
    return 0;
}

本题我的感受难点是存总步数(第几步第几步...)

因此用一个全局变量来存,并在每次输入的时候从新归零;

详细请参考前面的博客汉诺塔

 

问题 B: 字母全排列


时间限制: 1 Sec  内存限制: 128 MB



提交: 2  解决: 1  201501010119


提交状态讨论版 
  



题目描述 

编写一个程序,使用递归算法输出一个一维字符数组中全部字符的全排列,假设字符都不同。例如{'a','b','c'}的全排列为(a,b,c), (a,c,b), (b,a,c), (b,c,a), (c,a,b), (c,b,a) 



输入 

多组测试用例,每组输入一个正整数n(0<n<=26)。 



输出 

输出从a开始,连续n个字母的全排列,且每组输出之间用空格隔开。 



样例输入 Copy 

1
2




样例输出 Copy 

a

ab
ba
#include<bits/stdc++.h>
 
using namespace std;
 
void swap(char a[],int i,int j)   //交换函数
{
    int t=a[i];
    a[i]=a[j];
    a[j]=t;
}
void f(char a[],int k,int n) { if(k>=n) //只剩下一个元素 { for(int i=0;i<n;i++) printf("%c",a[i]); cout<<endl; } else { for(int i=k;i<n;i++) //循环用来判断每次排列谁作第一个,递归用来递归到下一个元素的判断 { swap(a,k,i); //还原 f(a,k+1,n); swap(a,k,i); //还原 } } } int main() { int n; while(cin>>n) { char a[27]; int i; int s=97; for(i=0;i<n;i++) //把须要的字母按顺序存进数组a { a[i]=s; s++; } f(a,0,n); cout<<endl; } return 0; }

 这个题和书上的数字全排列问题相似(划掉);

全排列问题的核心思想是:各个排列数轮流作第一个;

分两步:n=1,只有一个元素;n>1,一直递归到只剩下一个元素;

注意点:轮流作完了第一个后要还原!还原有两步!

 

问题 F: 幸运人士


时间限制: 1 Sec  内存限制: 128 MB



提交: 1  解决: 1  201501010119


提交状态讨论版 
  



题目描述 

一次大型派对的最后节目是选出一位幸运人士,该人士将得到派对组织者准备的一个钻石戒指。 
 而选择幸运人士的办法是让全部人员一字排列,而后从左至右点数,凡是奇数号的所有剔除。 
 对于剩下的人员,又从左至右点数,逢奇数号就剔除。 
 如此不断递归下去,直到只剩下一我的为止,此人即为幸运之人。 
 请设计一个递归算法计算幸运之人所在的位置。 




输入 

多组数据,每组输入一个正整数n。 



输出 

输出最后剩下的那我的的位置。 



样例输入 Copy 

1
2
3



样例输出 Copy 

1
2
2
#include <bits/stdc++.h>
 
using namespace std;
int f(int a,int b)
{
        if(a>1)
        {
 
        if(a%2==0)
    {
        b++;
        return f(a/2,b);
    }
    if(a%2!=0)
    {
        b++;
        return f(a/2,b);
    }
        }
    if(a==1)
        return b;
}
 
int main()
{
    int n;
    while(cin>>n)
    {
        int s,i,c;
        c=1;
       s=f(n,0);
       for(i=0;i<s;i++)
        c=c*2;
            cout<<c<<endl;
    }
    return 0;
}

算。。。水题?找规律?以前一直觉得用数组,后来室友发现了规律

 

问题 C: 九数组分数


时间限制: 1 Sec  内存限制: 128 MB



提交: 0  解决: 0  201501010119


提交状态讨论版 
  



题目描述 

1, 2, 3...9 这九个数字组成一个分数,其值刚好为1/3,要求每一个数字出现且只能出现一次,如何组合?编写程序输出全部的组合。 



输入 

无 



输出 

输出全部的结果,若是有多个,每条结果占一行。 
 结果的格式 : xxxx/xxxxx ,按照分子从小到大的顺序输出。
#include<bits/stdc++.h>
 
using namespace std;
 
int arr[2];
int k=0;
 
void f(int aa[],int m,int n)
{
 
    if(m==n)
    {
        int a,b;
    a=aa[3]*1000+aa[2]*100+aa[1]*10+aa[0];
    b=aa[8]*10000+aa[7]*1000+aa[6]*100+aa[5]*10+aa[4];
    if(a*3==b)
        arr[k++]=a;
    }
        else
        {
            int i;
            for(i=m;i<=n;i++)
            {
                swap(aa[m],aa[i]);
                f(aa,m+1,n);
                swap(aa[m],aa[i]);
            }
        }
 
    }
 
int main()
{
    int aa[]={1,2,3,4,5,6,7,8,9};
    f(aa,0,8);
        sort(arr,arr+2);
        for(int j=0;j<2;j++)
        printf("%d/%d\n",arr[j],arr[j]*3);
    return 0;
}

和全排列相似;

判断比值刚好为三分之一,将除法转换为乘法来算

 

问题 H: 汉诺塔-3


时间限制: 1 Sec  内存限制: 32 MB



提交: 1  解决: 1  201501010119


提交状态讨论版 
  



题目描述 


用1,2,...,n表示n个盘子,称为1号盘,2号盘,...。号数大盘子就大。经典的汉诺塔问题常常做为一个递归的经典例题存在。可能有人并不知道汉诺塔问题的典故。汉诺塔来源于印度传说的一个故事,上帝创造世界时做了三根金刚石柱子,在一根柱子上从下往上按大小顺序摞着64片黄金圆盘。上帝命令婆罗门把圆盘从下面开始按大小顺序从新摆放在另外一根柱子上。而且规定,在小圆盘上不能放大圆盘,在三根柱子之间一回只能移动一个圆盘。咱们知道最少须要移动2^64-1次.在移动过程当中发现,有的圆盘移动次数多,有的少 。 告之盘子总数和盘号,计算该盘子的移动次数. 



输入 


包含多组数据,首先输入T,表示有T组数据.每一个数据一行,是盘子的数目N(1<=N<=60)和盘号k(1<=k<=N)。




输出 


对于每组数据,输出一个数,到达目标时k号盘须要的最少移动数。




样例输入 Copy 

2
60 1
3 1



样例输出 Copy 

576460752303423488
4
#include<bits/stdc++.h>
 
using namespace std;
 
int main()
{
    int t,n,k;
    cin>>t;
    while(t--)
    {
        cin>>n>>k;
        int long long s,a;
        int i;
        s=1;
        a=n-k;
        for(i=0;i<a;i++)
        {
            s=s*2;
        }
        cout<<s<<endl;
    }
    return 0;
}

这个也算找规律?

贴一个别人总结的汉诺塔问题 

https://blog.csdn.net/FIELDOFFIER/article/details/45243105汉诺塔集合
相关文章
相关标签/搜索