郊游 ID:PICNIC

题目大意
仙女星幼儿园的快班小朋友们下周要到粟洞公园郊游。带队教师想在郊游时让两名学生组成一个小队进行活动。不过让两名不是朋友的学生组成一队会发生争执或者互不理睬。因此,必须由两名朋友关系的学生组队。
给定各学生的朋友关系详情,编写程序计算出所有可配对的不同方法。任何一个不相同的配对都将被视为一种不同的配对方法。例如,以下两种配对方法就属于不同的配对方法。
●(泰妍,杰西卡)(珊妮,蒂芬妮)(孝渊,俞利)
●(泰妍,杰西卡)(珊妮,俞利)(孝渊,蒂芬妮)

解题思路:
为了使用递归调用,首先将整个操作过程分解为几个小的操作。这道题中,将整个问题分解为m/2个小操作,每个小操作等同于对两名学生的组队。此时问题将变为“给定还未组队的学生名单时,计算出两名朋友间组成小队的组合个数”。因为名单中找出两名互为朋友关系的学生组队后,对剩下学生的组队又相当于前一步骤的操作过程。

出现的问题:
计算组合个数时会经常遇到重复相同答案的现象。为了解决这种错误,可采取只计算特定形态答案的方法。通常使用的方法是,在相同答案中以字典顺序只选择最先得到的答案。例如,忽略(2,3)、(0,1)或(1,0)、(2,3),而选择(0,1)、(2,3)。

为了强制这种属性,在各操作阶段只为序号最靠前的学生配上伙伴,即可解决前面提到的两种问题。对序号最靠前的学生而言,其伙伴的序号肯定比其靠后,所以不可能得到像(1,0)这一类的答案。又因为总是从序号最靠前的学生开始配对,所以也不可能出现像(2,3)、(0,1)这一类答案。代码6-5是按照这种思路编写的代码。

int n ;
bool areFriend[10][10];
// 若第take[i] = i 个学生找到了伙伴,则返回true,否则为false
int countPairings(bool take[10]){
    int firstFree = -1;
    for(int i =0;i<n;++i){
        if(!take[i]){
            firstFree = i;
            break;
        }
    }
    //所有的学生都匹配上了
    if(firstFree == -1)return 1;
    int ret = 0;
    //选择与学生组队的伙伴
    for(int pairWith = firstFree+1;pairWith<n;++i){
        if(!take[pairWith]&&areFriend[firstFree][pairWith]){
            take[firstFree] = take[pairWith] = true;
            ret += countPairings(take);
            take[firstFree] = take[pairWith] = false;
        }
    }
    return ret;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

落春只在无意间

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值