蓝桥杯第七届决赛:机器人塔

机器人塔

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

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

解题思路:
通过输入的A,B的值先确定 塔的层数,因为题目说明了保证人数的合理性,无论A,B给多少人,能堆出来的塔的层数一定是唯一确定的。然后从第一层到最后一层一次遍历,找到符合条件的数组塔,然后筛选出塔中A和B 的数目和给定的A,B数目相同的塔的数量。

#include<iostream>
using namespace std;

int A,B;
char arr[500][500];//数组塔
int deep=0;//塔的深度
char ab[2]={'A','B'};
int count=0;//符合条件的数目

bool isOk(int x,int y){//判断(x,y)位置的放置的A或B是否符合条件
	if(x==0||y==0){
		return true;
	}else{
		if(arr[x-1][y-1]=='A'){
			if(arr[x][y-1]!=arr[x][y]){
				return false;
			}
		}else{
			if(arr[x][y-1]==arr[x][y]){
				return false;
			}
		}
	}
	return true;
}
bool isTrue(){//判断该塔里A,B的数目是否和输入的A,B数目一样
	int x=0,y=0;
	for(int i=0;i<deep;i++){
		for(int j=0;j<=i;j++){
			if(arr[i][j]=='A'){
				x++; 
			}
			if(arr[i][j]=='B'){
				y++;
			}
		}
	} 
	if(x==A&&y==B){
		return true;
	}
	return false;
}
void dfs(int i,int j){//递归找出所有的塔
	if(i==deep){
		if(isTrue()){
			count++;
		}
	}else{
			for(int k=0;k<2;k++){
				arr[i][j]=ab[k];
				if(isOk(i,j)){
					if(j<i){
						dfs(i,j+1);
					}else{
						dfs(i+1,0);
					}
				}
			}	
	}			

}

int main(){
	cin>>A>>B;
	int s=A+B;
	int sum=0;
	for(int i=1;i<s;i++){//找到层数
		sum+=i;
		if(sum==s){
			deep=i;
			break;
		}	
	}		
	dfs(0,0);
	cout<<count<<endl;
}

之前的代码太麻烦了,再看的时候又写了一种简洁一点的:

#include<iostream>
#include<cstring>
using namespace std;
char arr[501][501]; 
char v[2]={'A','B'};
int r[2];//A ,B 机器人塔的数目 
int num;//塔的深度 
int sum=0;//符合条件的种类数 

void dfs(int row,int col){
	if(row<1){
		sum++;
		return;
	}else{
		if(row==num){ 
			for(int i=0;i<2;i++){
				if(r[i]-1>-1){
					arr[row][col]=v[i];
					r[i]--;
					if(col==row)
						dfs(row-1,1);
					dfs(row,col+1);
					arr[row][col]='C';
					r[i]++;
				}
			}
		}else{
			if(arr[row+1][col]==arr[row+1][col+1]){
				if(r[0]-1>-1){
					arr[row][col]=v[0];
					r[0]--;
					if(col==row)
						dfs(row-1,1);
					dfs(row,col+1);
						arr[row][col]='C';
					r[0]++;
				}
			}
			if(arr[row+1][col]!=arr[row+1][col+1]){
				if(r[1]-1>-1){
					arr[row][col]=v[1];
					r[1]--;
					if(col==row)
						dfs(row-1,1);
					dfs(row,col+1);
						arr[row][col]='C';
					r[1]++;
				}
			}
			
		}
	}
} 

 
int main(){
	cin>>r[0]>>r[1];//输入A的个数,B的个数 
	
	memset(arr,'C',sizeof(arr));//将塔初始化 
	// (1+k)*k/2=r[0]+r[1]  下面的for循环是为了找到这个k 
	int n=(r[0]+r[1])*2;
	for(int i=1;i<1000;i++){
		if(i*(i+1)==n){//根据等差数列公式找到塔应有的深度 
			num=i;
			break;
		}
	}
	dfs(num,1);//从最底层向上排 
	cout<<sum<<endl;
	return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值