第七届蓝桥杯决赛真题 - 机器人塔

题目:

机器人塔

X星球的机器人表演拉拉队有两种服装,A和B。
他们这次表演的是搭机器人塔。

类似:
A
B B
A B A
A A B B
B B B A B
A B A B B A

队内的组塔规则是:

A 只能站在 AA 或 BB 的肩上。
B 只能站在 AB 或 BA 的肩上。

你的任务是帮助拉拉队计算一下,在给定A与B的人数时,可以组成多少种花样的塔。

输入一行两个整数 M 和 N,空格分开(0< M,N<500),分别表示A、B的人数,保证人数合理性。

要求输出一个整数,表示可以产生的花样种数。

例如:
用户输入:
1 2

程序应该输出:
3

再例如:
用户输入:
3 3

程序应该输出:
4

资源约定:
峰值内存消耗 < 256M
CPU消耗 < 1000ms

请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。

注意: main函数需要返回0
注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
注意: 所有依赖的函数必须明确地在源文件中 #include , 不能通过工程设置而省略常用头文件。

提交时,注意选择所期望的编译器类型。

解答思路:
我们可以发现只需要确定最底层的情况,就可以依次向上推出每一层的情况,因此解决方法是:先用dfs列举出最底层的情况,然后向上递推判断这种情况是否满足,满足则答案加1。向上递推可以使用dp进行优化,从而加快速度。

知识点:
dfs搜索、递推、dp(动态规划)

C++代码:

#include <iostream>
using namespace std;

int M, N, H;
int ans = 0;
char ch[500][500];

//用于进行dp优化 
int flag[500][500][500] = {0};
bool dp[500][500][500];

//判断m个A,n歌B是否能组成高度为H的三角的第h层 
int search(int m, int n, int h){
    if(flag[m][n][h] != 0){
        return dp[m][n][h];
    }

    if(h == H){
        flag[m][n][h] = 1;
        return dp[m][n][h] = true;
    }

    for(int i = 0; i < H - h; ++ i){
        if(ch[h - 1][i] == ch[h - 1][i + 1]){
            if(m <= 0){
                flag[m][n][h] = 1;
                return dp[m][n][h] = false;
            }
            ch[h][i] = 'A';
            -- m;
        }
        else{
            if(n <= 0){
                return dp[m][n][h] = false;
            }
            ch[h][i] = 'B';
            -- n;
        }
    }

    flag[m][n][h] = 1;
    return dp[m][n][h] = search(m, n, h + 1);
}

//对最底层的情况进行列举 
void dfs(int m, int n, int i){
    if(i == H){
        if(search(m, n, 1)){
            ++ ans;
            //输出三角
            /*for(int i = 0; i < H; ++ i){
                for(int j = 0; j < H; ++ j){
                    cout << ch[i][j] << " ";
                }
                cout << endl;
            }
            cout << endl;*/
        }
        return;
    }

    if(m){
        ch[0][i] = 'A';
        dfs(m - 1, n, i + 1);
    }
    if(n){
        ch[0][i] = 'B';
        dfs(m, n - 1, i + 1);
    }
}

int main(){
    cin >> M >> N;
    for(H = 0; H*(H + 1) != 2*(M + N); ++ H);
    dfs(M, N, 0);
    cout << ans << endl; 
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值