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的人数,保证人数合理性。
要求输出一个整数,表示可以产生的花样种数。
输入
输入一行两个整数 M 和 N,空格分开(0<M,N<500),分别表示A、B的人数,保证人数合理性。
输出
要求输出一个整数,表示可以产生的花样种数。
样例输入
1 2
样例输出
3
做这道题需要看穿问题的本质是什么
我们不需要去一层层枚举每层的情况,而是直接看底边上是什么情况就好
因为倒数第二层的字母是依据倒数第一层的字母进行排列的,同理倒数第三层的字母是依据倒数第二层的字母排列···以此类推
我们得到的结论就是仅仅知道最后一层的情况就可以推出整个塔是怎么构成的
所以我们第一步是枚举所有底边上的情况
然后用递推把整个机器人塔建好,统计其中的a或b的字母个数看是不是满足题面给出的情况
//递推类型题目,只要给定了底边,那么上面都是完全固定的,
//那么我们考虑把整个机器人阵都摆好之后核查a和b的个数就可
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m;
int sum,bottom;
int ans[1010];
int backup[1010];
int res;
bool dfs_com() //dfs_com函数不仅依据底边进行建塔,还统计依照底边建塔后a和b的数量是不是符合题意
{
int sum_a = 0,sum_b = 0;
for(int i=1;i<=bottom;i++)
{
if(ans[i]) sum_a++;
else sum_b++;
}
int x = bottom;
while(x>1) //每一层的上面一层都比这一层少一个字母,循环覆盖ans数组就能层层递推,终止条件当然是循环到第二层的时候
{
for(int i=2;i<=x;i++)
if(ans[i]!=ans[i-1])
{
ans[i-1] = 0;
sum_b++;
}
else
{
ans[i-1] = 1;
sum_a++;
}
x--;
}
if(sum_a==n && sum_b==m) return 1;
else return 0;
}
void dfs_bot(int step)
{
if(step>bottom)
{
if(dfs_com()) res++;
return;
}
ans[step] = 1; //1代表A,只能在00或者11上面
dfs_bot(step+1); //0代表B,只能在10或者01上面
ans[step] = 0;
dfs_bot(step+1);
}
int main()
{
cin>>n>>m;
for(int i=1;;i++)
{
sum+=i;
if(sum==n+m)
{
bottom = i; //先处理出来底边上应该有多少字母
break;
}
}
dfs_bot(1); //dfs_bot来搜尽所有底边上的情况
cout<<res;
return 0;
}
要加油喂!!!