算法(c++)——循环比赛日程安排问题

目录

一、问题描述

二、解题思路

三、代码

四、结果

五、总结

六、完整程序代码包

ShiYan_1_XunHuanBiSaiRiChengAnPai.rar-讲义文档类资源-CSDN下载算法(c++)——循环比赛日程安排问题更多下载资源、学习资料请访问CSDN下载频道.https://download.csdn.net/download/lcf0000/55674158


一、问题描述

        循环比赛日程安排问题:设有n(n=2^k)支队伍參加循环赛,循环赛共进行n-1天,每支队伍要与其它n-1支队伍比赛一场,且每支队伍每天必须比赛一场,不能轮空。试按此要求为比赛安排日程。运用分治递归法解决该问题。

二、解题思路

        首先安排奇数下标位置与偶数下标位置之间的比赛,就有n/2,team[2k]=2k,全部奇数号组成一个序列[1,3...n-1],然后循环移动n/2-1次(比方第2个序列就是[3,5...n-1,1]),然后将该序列填充在team的奇数位置上。

        接下来将队伍一分为二,奇数为一组,偶数为一组,分配安排其内部比赛(由于奇偶数之间前面已经安排过了啦)。以奇数组[1,3,5,7]为例(n=8为例说明),我们仍然先安排奇数下标位置与偶数下标位置之间的比赛,也就是[15][37]之间的比赛,共同拥有2(n/4)

        接下来,再将队伍一分为二,得到[15],[37],[04],[26],对每一部分,仍然是先安排奇数下标位置与偶数下标位置之间的比赛,共1(n/8)。此时已不可再分出子队伍,计算结束。

三、代码

#include <iostream>
#include <stdio.h>
#include <math.h>

using namespace std;

// team: 比赛安排结构,team[2j] vs team[2j+1]
// n:  team的总数,n = 2^k
// id:   第id轮的安排,id的范围[1, n-1]
void game(int *team, int n, int id){
    int base = 2;
    while (id > n/base){
        id -= n/base;
        base <<= 1;
    }
    for (int i=0; i<base/2; ++i){
        int start = i+base/2+(id-1)*base;
        for (int j=0; j<n/base; ++j){
            team[i*2*n/base+2*j] = base*j+i;
            team[i*2*n/base+2*j+1] = (start+base*j)%n;
        }
    }
}

void dump(int *arr, int n){//输出每天比赛安排
    for (int i=0; i<n; i+=2)
        printf("%02d-%02d ", arr[i], arr[i+1]);
    printf("\n");
}
int main(){
    int k;
    printf("请输入k的值:")
    scanf("%d",&k);
    const int n = pow(2, k);
    int team[n];
    for (int i=1; i<n; ++i){
        game(team, n, i);
        printf("[%02d] ", i);
        dump(team, n);
    }
    return 0;
}

四、结果

        结果说明:第一行,输入k的值为4,意味着队伍总数n=2k;接下来的部分为每天的赛程安排,以第一行为例,[01]表示第一天,其后边的形如“00-01”的表示00号队伍与01号队伍比赛,以此类推,最终结果正确。

五、总结

1、分治的全称称为“分而治之”,分治即是将大问题划分为若干个规模较小、可以直接解决的子问题,然后解决这些子问题,最后将这些子问题的解合并起来,即是原问题的解。

2、分治的步骤

        分治法的目的就是为了把无法解决的大问题分解成若干个能够解决小问题。通常来说,分治法可以归纳为三个步骤:

(1)分解,将原问题分解成若干个与原问题结构相同但规模较小的子问题;

2)解决,解决这些子问题。如果子问题规模足够小,直接求解,否则递归地求解每个子问题;

3)合并,将这些子问题的解合并起来,形成原问题的解。

3、对于本次实验问题:设有n=2^k个选手参加循环赛,要求设计一个满足以下要求比赛日程表:

1)每个选手必须与其它n-1个选手各赛一次;

2)每个选手一天只能赛一次。

        按照上面的要求,可以将比赛表设计成一个n行n-1列的二维表,其中第i行第j列的元素表示和第i个选手在第j天比赛的选手号。

        采用分治策略,可将所有参加比赛的选手分成两部分,n=2^k个选手的比赛日程表就可以通过n=2^k-1)个选手的的比赛日程表来决定。递归的执行这样的分割,直到只剩下两个选手,比赛日程表的就可以通过这样的分治策略逐步构建。

六、完整程序代码包

ShiYan_1_XunHuanBiSaiRiChengAnPai.rar-讲义文档类资源-CSDN下载算法(c++)——循环比赛日程安排问题更多下载资源、学习资料请访问CSDN下载频道.https://download.csdn.net/download/lcf0000/55674158

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

高冷男孩不吃苹果

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

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

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

打赏作者

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

抵扣说明:

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

余额充值