题目描述:有n个老师和n个学生,n个老师要带n个学生过河,要求一个老师带一个学生,即老师要在学生前面,学生不能单独过河,求出所有的合法组合。T代表老师,C代表学生,按字母顺序输出
输入范例
2
输出范例
TCTC
TTCC
分析:
这题类似求多重括号是否合法,例如((()))是合法的,而(()))(则是非法的
可以用二进制的方式表示,T代表1,C代表0
判断是否合法的方法是定义一个变量,变量遇到1则加1,遇到0则减1,遍历完成时变量的值为0才是合法的,如果变量在某一刻出现为负数,那么肯定是不合法的,可以直接返回了
题目要求n个学生和n个老师,那么表示的二进制数必须是2n位的(第一位必须是1)
二进制为2n位的最小值规律:
n=1 ,10B = 2^1
n=2,1000B = 2^3
n=3,100000B = 2^5
……
综上,可以得出n=k,最小值为2^(2k-1)
那么最大值又是多少呢?是全部为1吗(2^2n-1)?
当然不是啦,前面1的数最多只能有n位
例如n=2,那么到1100就应该停止了
最大值规律:
n=1,10B = 2^1
n=2,1100B = 2^2+2^1
n=3,111000B = 2^5+2^4+2^3
n=4,111110000B = 2^7+2^6+2^5+2^4
……
综上,可以得出n=k,最大值为2^k+2^(k+1)+...+2^(2k+1)
代码如下
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
// min:2^(2n-1),max:2^n+...+2^(2n-1)
int min = 1 << (2 * n - 1);// 2的2n-1次方
int max = calEnd(n, 2 * n - 1);
for (int j = min; j <= max; j++) {
String binary = Integer.toBinaryString(j);
char[] chs = binary.toCharArray();
if (judge(chs)) {
output(chs);
}
}
}
private static void output(char[] chs) {
for (int i = 0; i < chs.length; i++) {
if (chs[i] == '1') {
System.out.print("T");
} else {
System.out.print("C");
}
}
System.out.println();
}
private static boolean judge(char[] chs) {
int flag = 0;
for (int i = 0; i < chs.length; i++) {
if (chs[i] == '1') {
flag++;
} else {
flag--;
if (flag < 0) {
return false;
}
}
}
if (flag == 0) {
return true;
}
return false;
}
private static int calEnd(int l, int r) {
int sum = 0;
for (int i = l; i <= r; i++) {
sum += (1 << i);
}
return sum;
}
}