题目:
机器人塔
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;
}