蓝桥杯 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];
}
}