问题:
有两队选手每队5人进行一对一的比赛,甲队为A、B、C、D、E,乙队为J、K、L、M、N,经过抽签决定比赛对手名单。规定A不和J比赛, M不和D及E比赛。列出所有可能的比赛名单。
分析:
抽签决定比赛对手,为了找出所有可能的比赛方案,可以假设由甲组成员与选择对手,故在无限制条件的情况下,甲组的每个选手均有5种选择,由此可建立对手池:
A:J K L M N
B:J K L M N
C:J K L M N
D:J K L M N
E:J K L M N
用一个二维数组去存储这五个对手池,即下面代码中的bisai[5][5]二维数组;
然后需要确定限制条件:
(1)A不和J比赛, M不和D及E比赛
(2)比赛为一对一,即每组的一位选手只能对战另外一组的一位选手,不可一对多
解决方案:
每次均为A选手先在其对手池中选择对手,然后再到B,以此类推下去。
意味着需要5重循环进行排列;
且需要记住每个选手所选择的对手,以免重复。
意味着需要5个标记变量,用于记住每位选手所选择的对手;
源代码如下:
package enumeration_and_recursion;
/*有两队选手每队5人进行一对一的比赛,甲队为A、B、C、D、E,乙队为J、K、L、M、N,
* 经过抽签决定比赛对手名单。规定A不和J比赛, M不和D及E比赛。列出所有可能的比赛名单。
*/
public class Example3 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
char Jia[]=new char[]{'A','B','C','D','E'};//甲组
char Yi[]=new char[]{'J','K','L','M','N'};//乙组
char bisai[][]=new char[5][5];//对手池,第0行为A的对手池,第1行为B的对手池
//第2行为C的对手池,第3行为D的对手池,第4行为E的对手池
for(int i=0;i<bisai.length;i++) {
for(int j=0;j<5;j++) {//建立ABCDE每个选手的所有对手可能(在无限制条件情况下)
bisai[i][j]=Yi[j];
}
}
/*//ABCDE每个输出所有的对手可能
* char temp='A';
for(int i=0;i<5;i++,temp++) {
for(int j=0;j<5;j++) {
System.out.print(temp+" VS "+bisai[i][j]+" ");
}
System.out.println();
}
*/
char temp1='A',temp2='B',temp3='C',temp4='D',temp5='E';
int i,j,k,x,y,count=0;
for(i=0;i<5;i++) {//选择A的对手
if(bisai[0][i]=='J') {//如果A的对手不能是J,跳过J
continue;
}
for(j=0;j<5;j++) {//选择B的对手
if(j==i) {//B的对手不能是A已选的对手
continue;
}
for(k=0;k<5;k++) {//选择C的对手
if(k==j||k==i) {//C的对手不能是A和B已选的对手
continue;
}
for(x=0;x<5;x++) {//选择D的对手
if(x==i||x==j||x==k||bisai[3][x]=='M') {
continue;//同上,且对手不能为M
}
for(y=0;y<5;y++) {//选择E的对手
if(y==i||y==j||y==k||y==x||bisai[4][y]=='M') {
continue;//同上,且对手不能为M
}
count++;//记录有多少种方案
System.out.print(count+":");
System.out.print(temp1+" vs "+bisai[0][i]+" ; ");
System.out.print(temp2+" vs "+bisai[1][j]+" ; ");
System.out.print(temp3+" vs "+bisai[2][k]+" ; ");
System.out.print(temp4+" vs "+bisai[3][x]+" ; ");
System.out.print(temp5+" vs "+bisai[4][y]);
System.out.println();
}
}
}
}
}
}
}