两支乒乓球队进行比赛,各出3人,甲队有A、B、C三人,乙队有X、Y、Z三人。
A不跟X比赛,C不跟X或Z比赛。
请问应该如何分组?
思路:
前面用3个嵌套的循环来解决了问题。但是,假如参赛人数多了以后,嵌套的循环太深了。
尝试寻找更通用、简洁的办法——类似N皇后问题的解决思路,递归。
甲组可以依次固定,A先选择乙组的对手;然后B来选对手,A选过的对手不能再选,只需要遍历乙组,发现已经被A选过了,就判断不能选;同样递归到C来选择。
最后再用“A不跟X比赛,C不跟X或Z比赛”的条件过滤,得到最终答案。
#define Team_Len 3
//当前位置npos,判断当前能否选nSelVal序号的对手。从前面0-->(npos-1)已经选了的对手里只要找到当前候选序号,就判断不能选,返回0表示false
int canselect(int Team[], int npos, int nSelVal)
{
int result = 1;
for(int i=0; i<npos; i++)
{
if(Team[i]==nSelVal)
{
result = 0;
break;
}
}
return(result);
}
//递归函数,递归退出条件是到最后一个选择对手
void selectTeamer(int Team[], int nDim, int MaxVal, int npos)
{
if(npos<(nDim-1))
{
//not the last column
for(int val=0; val<=MaxVal; val++)
{
if(canselect(Team, npos, val)) //如果当前对手能够被选择
{
Team[npos]=val;
//还不是最后一个,继续下一个位置选择对手
selectTeamer(Team, nDim, MaxVal, npos+1);
}
}
}
else
{
//当到达最后一个,选择合适的对手,然后得到一个结果,因为前面(n-1)个对手都已经选择好了
for(int val=0; val<=MaxVal; val++)
{
if(canselect(Team, npos, val))
{
Team[npos]=val;
if((Team[0]!=0)&&(Team[2]!=0)&&(Team[2]!=2))
{
for(int i=0; i<Team_Len; i++)
printf("%c vs %c\n", 'A'+i, Team[i]+'X');
}
}
}
}
}