机器人塔(蓝桥杯)

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
解题思路:根据题目我们可以发现,要想拼成一个完整的塔,必须保证A和B都要用完,而上面的服装类型都是根据下面的服装类型决定的,于是我们只需要搜索最下面一层塔的所有服装情况的全排列,在这个基础上建立塔,每使用一个A或B相应的服装数量减少,如果在建立途中就已经用完了A或B说明这种方案不可行,直接剪掉,也就是我们说的剪枝。搜索完所有方案便能得出最终结果
这里我用二维整型数组a存储塔,1表示A,2表示B

#include <bits/stdc++.h>
using namespace std;
int map1[1001],a[501][501],N,M,n,A,B,ans=0;//map1表示映射 根据A和B的和能算出对应的最下面一层是多少 
void dfs(int step)//表示最后一层的第step列 
{  int i,j;
	if(A<0||B<0) return ; //如果建立过程中就已经消耗完其中一种 直接剪枝 
	else
	if(step>map1[n])//如果排列完 
	{ int a1=A,b1=B;//a1,b1表示剩余A和B的数量,防止后面建塔不满足跳出后影响到原来的A和B值 
	  for(i=map1[n]-1;i>=1;i--)//开始根据最下面一层建塔 
	   { for(j=1;j<=i;j++)
	      {
	      	
	      	if(a[i+1][j+1]==a[i+1][j])//A只能放在两个相同的上面 
	      	{ a[i][j]=1; a1--;
	      	}
	      	else  //B只能放在两个不同的上面 
	      	{ a[i][j]=2;b1--;
	      	}
			  if(a1<0||b1<0) return ;//如果建立过程中就已经消耗完其中一种 直接剪枝 
	      }
	   }
	   ans++;//塔已建成 ,方案数+1 
	   return ; 
	} 
	else
	{
		a[map1[n]][step]=1;//这一列建A 
		A--; //对应数量-1 
		dfs(step+1);//搜索下一列 
		A++; //回溯 
		a[map1[n]][step]=2;//这一列建B 
		B--;//对应数量-1 
		dfs(step+1);//搜索下一列 
		B++;//回溯 
		
	}	
}
int main()
{
	cin>>M>>N;
	n=M+N; //总数 
	A=M; //A的数量 
	B=N; //B的数量 
	int i,t;
	map1[1]=1,t=1;
	for(i=2;i<=500;i++)//算出映射数组 便可得到最下面一层有多少个 
	{   t=t+i;
		map1[t]=i;

	}
	dfs(1);//开始全排列最下面一层 
	printf("%d",ans);
	return 0;
} 
上一篇:2020.9.19 ICPC网络选拔赛 第一场


下一篇:map转listmap