蓝桥杯 16决赛 A4 机器人塔(dfs)

蓝桥杯 16决赛 A4 机器人塔(dfs)

机器人塔
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

===========================

思路:
从上往下遍历,虽然同样两次dfs,但是代码相同,无需复写

public class 细节_机器人塔_4 {
	static int a ,b ,ans;
	static char[][] cha;
	public static void main(String[] args) {
		init();
		dfs(0 ,0 ,0 ,'A');	//最顶层可能是或者B把
		dfs(0 ,0 ,0 ,'B');
		System.out.println(ans /2);	//并不是因为A和B做顶层时候有重复图样,而是每次dfs有两次分支(每次都使得ans++)
	}
	private static void dfs(int lev, int a_ava, int b_ava ,char head) {
		if(lev ==cha.length) {
			ans ++;
			return ;
		}
		cha[lev][0] =head;	if(head =='A') a_ava ++; else b_ava ++;	//每行头元素都是不受上层元素限制的
		for(int i =1 ;i <cha[lev].length ;i ++) {
			if((cha[lev][i -1] =='A' &&cha[lev -1][i -1] =='A') ||(cha[lev][i -1] =='B' &&cha[lev -1][i -1] =='B')) {
				a_ava ++; cha[lev][i] ='A';
			}else {
				b_ava ++; cha[lev][i] ='B';
			}
			if(a_ava >a ||b_ava >b) return ;	//剪枝
		}
		dfs(lev +1 ,a_ava ,b_ava ,'A');
		dfs(lev +1 ,a_ava ,b_ava ,'B');
	}
	private static void init() {
		Scanner sc = new Scanner(System.in);
		a =sc.nextInt();
		b =sc.nextInt();
		sc.close();
		int c =a +b ,s =1 ,sum =1;
		while(c !=sum) sum += ++s;	//得到行数s
		cha =new char[s][];
		//这里为什么不一次性声明所有子数组长度均为数组长?
		//->line:79 for循环条件可以更容易写
		for(int i =1 ;i <=s ;i ++) cha[i -1] =new char[i];
	}
}

猜你喜欢

转载自blog.csdn.net/weixin_43638238/article/details/107524033