题目描述
本题为代码补全填空题,请将题目中给出的源代码补全,并复制到右侧代码框中,选择对应的编译语言(C/Java)后进行提交。若题目中给出的源代码语言不唯一,则只需选择其一进行补全提交即可。复制后需将源代码中填空部分的下划线删掉,填上你的答案。提交后若未能通过,除考虑填空部分出错外,还需注意是否因在复制后有改动非填空部分产生错误。
9名运动员参加比赛,需要分3组进行预赛。 有哪些分组的方案呢?
我们标记运动员为 A,B,C,... I。
下面的程序列出了所有的分组方法。
解题思路:
相信很多读者是因为在蓝桥杯练习系统上面跑不通才来找博客一探究竟的,笔者这里想说其实蓝桥杯的系统存在着各种漏洞,不单是这道题,还有很多道都是存在着评判系统的漏洞,也就是说大多数读者其实都已经懂得了这个算法的思想并已经做出来该道题了,只是评判系统"人工判死"了而已。不过读者还是简单讲一下这个算法的解题思路,照顾一下算法小白们。
这道题其实用的就是一个暴力求解的算法思想,对九个人的所有排列进行一个 for 循环,首先用主方法中的 i j k 进行一个标记,比方说一开始我们的 a[0] = 1 , a[1] = 1 , a[2] = 1 , 剩下的位置全是初始化的 0 ,接着将字符串 s = "ABC" 和数组首地址 a 传到子函数 f 中进行解析,首先选中的三个也就是我们组队的角度去看的选中,那么就不能再次选中以免重复选的情况发生,故子函数 f 中每一次遍历都会先判断是否 a[x] == 1 ? ,若是的话就 continue 继续下一个的判断,否则就让该位置的数组值 = 1 表示这个位置对应的人也被选中了,以此类推,直到进入子函数 f 的最内层循环的时候表示前面的六个人都选好了,那么这里剩下的三个人,也就是数组上值为 0 的三个下标的人都还没被选中,故这里直接进行一个输出就行。
最后要说明一点就是,其实很多同学都是在纠结评判系统给的代码中,子函数 f 中的第三层循环内输出前为啥还要进行一个判断 k == 3 呢?其实还是那句话,蓝桥杯的系统还不够完善,可以说 bug 随处可见,这里只需要把这行代码去掉即可,有疑问的同学可以找一下往年的卷子找到这道题,你会发现上面没有这行判断语句。
该算法的 Java 代码实现如下:
public class Main{
public static String remain(int[] a) {
String s = "";
for (int i = 0; i < a.length; i++) {
if (a[i] == 0)
s += (char) (i + 'A');
}
return s;
}
public static void f(String s, int[] a) {// s = ABC a = 1 1 1 i1 j1 k1 0 0 0
for (int i = 0; i < a.length; i++) {
if (a[i] == 1)
continue;
a[i] = 1;
for (int j = i + 1; j < a.length; j++) {
if (a[j] == 1)
continue;
a[j] = 1;
for (int k = j + 1; k < a.length; k++) {
if (a[k] == 1)
continue;
a[k] = 1;
System.out.println(
s + " " + (char) (i + 'A') + (char) (j + 'A') + (char) (k + 'A') + " " + remain(a));
a[k] = 0;
}
a[j] = 0;
}
a[i] = 0;
}
}
public static void main(String[] args) {
int[] a = new int[9];
a[0] = 1;
for (int b = 1; b < a.length; b++) {
a[b] = 1;
for (int c = b + 1; c < a.length; c++) {
a[c] = 1;
String s = "A" + (char) (b + 'A') + (char) (c + 'A');// s = "ABC"
f(s, a);
a[c] = 0;
}
a[b] = 0;
}
}
}