2016年第七届蓝桥杯 - 国赛 - C/C++大学B组 - D. 机器人塔

机器人塔

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 , 不能通过工程设置而省略常用头文件。

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

Ideas

按照组塔规则,只要最底下一层的排列确定了,那么从下往上的机器人排列就确定了。

所以我们只需要搜索最底下一层的所有排列情况,然后判断这种情况是否可以利用所有的机器人组成相应的塔结构。

机器人塔每一层的数量是公差为1的等差数列,由求和公式:a1*n+[n*(n-1)*d]/2,得机器人总数 num = 1 * n + [n * (n - 1)] / 2,其中n表示层数。

设A的人数为num_a,B的人数为num_b,那么 num_a + num_b = 1 * n + [n * (n - 1)] / 2,然后我们可以通过解方程得到机器人塔的层数。

接下来就是正常的DFS的套路了,搜索最下面一层所有排列情况,然后再定义一个check函数用来判断当前排列情况是否满足要求。

Code

C++

#include <cmath>
#include <cstring>
#include <iostream>

using namespace std;

int num_a, num_b, line;
char map[45][45];
long long ans;

bool check() {
    int a = 0, b = 0;

    for (int i = 1; i < line + 1; i++)
        for (int j = 1; j < i + 1; j++)
            if (map[i][j] == 'A') a++;
            else b++;
    if ((a != num_a) || (b != num_b)) return false;
    return true;
}

void init() {
    for (int i = line; i > 1; i--)
        for (int j = 1; j < i; j++)
            if (map[i][j] == map[i][j + 1])
                map[i - 1][j] = 'A';
            else map[i - 1][j] = 'B';
}

void dfs(int y) {
    if (y == line + 1) {
        init();
        if (check()) {
            ans++;
        }
        return;
    }
    map[line][y] = 'A';
    dfs(y + 1);
    map[line][y] = 'B';
    dfs(y + 1);
}

int main() {
    cin >> num_a >> num_b;
    int temp = sqrt(1 + 8 * (num_a + num_b));
    line = (temp - 1) / 2;

    dfs(1);
    cout << ans << endl;
    return 0;
}

Python

from math import sqrt

maps = [[None] * 50 for _ in range(50)]


def dfs(y):
	if y == level:
		a, b = 0, 0
		for i in range(level - 2, -1, -1):
			for j in range(i + 1):
				maps[i][j] = 'A' if maps[i + 1][j] == maps[i + 1][j + 1] else 'B'
		for i in range(level):
			for j in range(i + 1):
				if maps[i][j] == 'A':
					a += 1
				elif maps[i][j] == 'B':
					b += 1
		if a == num_a and b == num_b:
			global ans
			ans += 1
		return
	
	maps[level - 1][y] = 'A'
	dfs(y + 1)
	maps[level - 1][y] = 'B'
	dfs(y + 1)


if __name__ == '__main__':
	ans = 0
	num_a, num_b = map(int, input().split())
	level = int((sqrt(1 + 8 * (num_a + num_b)) - 1) / 2)
	dfs(0)
	print(ans)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大风车滴呀滴溜溜地转

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值