您的位置:首页 > 其它

比赛分组(二)——更通用的解法

2016-03-04 18:24 381 查看
     两支乒乓球队进行比赛,各出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');

                }

            }

        }

    }

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: