递归+分治+回溯

问题 D: 红红的汉诺塔

题目描述
李红红今天听了汉诺塔的问题,陷入了顿悟的状态,顿悟结束后,他对汉诺塔的了解到达了一个新的层次
他回到家拿到汉诺塔后,突然很想知道汉诺塔层数为n的时候,编号为x 的那层移动了多少次,编号是从1到n。 从最小的那个开始编号,即最小的那个为1, 最大的那个为n。
比如李红红有一个5层的汉诺塔,现在他想知道编号为 3 的那层移动了多少次,则输出两个数字,一个总移动数字,一个3层移动数字
5层的汉诺塔,一共移动了31次,第三层移动了4次
当然也可以发现最大的那层即5层移动1次,最小的即1号移动了16次
红红希望大家使用递归算出他想要的结果
输入
多组测试样例
每组测试一行 n 和 x ( 0 < n < 20 0 < x <= n)
n为汉诺塔层数,x为需要知道的那层
输出
两个数字, 一个总移动次数,一个编号为 x 层的移动次数
样例输入
1 1
5 3
样例输出
1 1
31 4
提示
编号是从最小那层开始的,最小的那层编号为1

#include <cstdio>
#include <cmath>
#include <iostream>
using namespace std;
int flag,ans;  //flag为总的移动数  ans为第x个盘子移动数
void hanio(int n,int x){
    if(n==1){
      flag++;
      if(x==1) 
         ans++;
    }
    else{
        hanio(n-1,x);  //递归分治
        flag++;
        if(x==n)
           ans++;
        hanio(n-1,x);  //递归分治
    }
}
//int sum(int x){  //也可以用for循环 从最底层开始每层的移动数*2 最底层只移动一次
 //   int s=1;
  //  for(int i=1;i<=x;i++){
  //      s*=2;
   // }
    //return s;
//}
  
int main()
{
    int n,x;
    while(cin>>n>>x){
        flag=0;
        ans=0;
        hanio(n,x);
        cout<<flag<<" "<<ans<<endl;
          
    }
    return 0;
}

问题 E: Nine queen
题目描述
在一个9×9的方格棋盘上放置了9个皇后,使得他们不相互攻击(即任意两个皇后不允许处在同一排,同一列,也不允许许处在与棋盘边框成45°的斜线上。你的任务是输出字典序最小的一组解。
棋盘列位置下标从 1 开始!
输入

输出
输出每个九皇后列位置字典序最小的一组解。每两个数之间有一个空格,行末没有多余空格。

#include <cstdio>
#include <cmath>
#include <iostream>
using namespace std;
int row[9];  //定义一个存放皇后位置的数组,数组的下标为行,值为列
int flag=1;  
void nqueen(int now){
    if(now == 9 && flag){    
        for(int i = 0; i < 9; i++){
            cout << row[i] << ' ';
        }
        flag = 0;  //只输出第一个序列,所以之前flag等于1,当输出第一个序列后让他等于0,之后就不会输出
        cout << endl;
        return;
    }
    int j;
    for(int i = 1; i <= 9; i++){  //i为列
        for(j = 0; j < now; j++){   //row为当前要放皇后的行数 j为行数
            if(i == row[j] || abs(now - j) == abs(i - row[j]))  //如果存在是前面皇后的列和对角线上就break
                break;   
        }
        if(j == now){  //如果遍历到当前要放的这个行数就说明此列可以放   
            row[now] = i;
            nqueen(now + 1);  //到下一层递归
        }//如果都没法放就退出此层递归,回到上一层递归,并且继续上一次的i循环
    }
}
 
int main()
{
    nqueen(0);
    return 0;
}

问题 F: 爱吃车厘子的丹丹

题目描述
丹丹是一个喜欢吃车厘子的女孩子,第一天她买了好多个车厘子,马上就吃了车厘子的一半再多一个;第二天,吃了剩下的车厘子的一半又多一个;以后每天都吃前一天剩下的一半多一个,到第n天,只剩下m个车厘子。已知车厘子 t 元一个,丹丹妈妈想知道丹丹第一天花了多少钱买车厘子
输入
每一行有三个数n,m,t
有多组输入,用 int 定义不会溢出,n m t 均为正整数
输出
买车厘子需要的钱数
样例输入
5 2 3
7 1 2
样例输出
186
380

#include<cstdio>
#include<iostream>
using namespace std;
  
int digui (int n,int m)  //n为天数,
{
    if(n==0){
        return m;
    }else
        return 2*(digui(n-1,m)+1);       
}
  
int main(){
      
    int n,m,t;
    while(cin>>n>>m>>t){
        cout<<digui(n-1,m)*t<<endl;
    }
      
    return 0;
}

问题 G: 红红爬楼

题目描述
红红把每次爬楼都当作一种乐趣,由于某种原因他每次只能向上爬一格或者两格,他想知道他到底有多少种方式爬到楼顶。已知它的初始位置在第零层,楼梯共有n层。到第n层表示已经爬到楼顶。
输入
输入n(0 < n < 20),表示楼梯台阶的总数。
输出
输出一个整数,表示红红爬到楼顶的总方案数。
样例输入
2
样例输出
2
提示
对于第一个样例,从第一层到第二层有两种方法,即先从第0层上一个台阶到第1层,在层第一层上一个台阶到第二层,第二种方案为直接从第一层跨两步到达第二层。所以共有两种方法。


//使用递归枚举,如果符合,方案数++
#include <cstdio>
#include <cmath>
#include <iostream>
#include<queue>
#include<cstring>
using namespace std;
int n,flag=0;
void sum(int now){
    if(now==n){
       flag++;
    }
    else if(now>n)
        return;
    else{
        int i; 
        for(i=1;i<=2;i++)  //回溯到上一层递归,继续试i
             sum(now+i);
        }
     
}
 
int main()
{
    cin>>n;
    sum(0);
    cout<<flag<<endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值