java 循环赛问题_算法——循环赛日程安排问题

一、问题背景

设有n=2k个选手要进行网球循环赛,要求设计一个满足以下要求的比赛日程表:

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

②每个选手一天只能赛一次。

二、问题分析

按此要求,可将比赛日程表设计成一个n×(n-1)的二维表,其中,(i, j)表示和第i个选手在第j天比赛的选手。

•将所有参赛的选手分为两部分

n=2^k个选手的比赛日程表就可以通过为n/2=2^(k-1)个选手设计的比赛日程表来决定。

•递归地执行这种分割

•直到只剩下2个选手(递归出口)比赛日程表的制定就变得足够简单

只要让这2个选手进行比赛即可

•求解过程是自底向上的迭代过程,其中图(c)左上角和左下角分别为选手1至选手4以及选手5至选手8前3天的比赛日程

•将左上角部分的所有数字按其对应位置抄到右下角,将左下角的所有数字按其对应位置抄到右上角,这样,就分别安排好了选手1至选手4以及选手5至选手8在后4天的比赛日程,如图(c)所示。具有多个选手的情况可以依此类推。

•把求解2k个选手比赛日程问题划分成依次求解21、22、…、2k个选手的比赛日程问题,换言之,2k个选手的比赛日程是在2^(k-1)个选手的比赛日程的基础上通过迭代的方法求得的。

•在每次迭代中,将问题划分为4部分:

①左上角

•左上角为2^(k-1)个选手在前半程的比赛日程;

②左下角

•左下角为另2^(k-1)个选手在前半程的比赛日程,由左上角加2^(k-1)得到,例如22个选手比赛,左下角由左上角直接加2得到,23个选手比赛,左下角由左上角直接加4得到;

③右上角

•将左下角直接抄到右上角得到另2^(k-1)个选手在后半程的比赛日程;

④右下角

•将左上角直接抄到右下角得到2^(k-1)个选手在后半程的比赛日程;算法设计的关键在于寻找这4部分元素之间的对应关系

三、算法描述

void GameTable(int k, int a[ ][ ])

{

// n=2k(k≥1)个选手参加比赛,//二维数组a表示日程安排,数组下标从1开始n=2; //k=0,2个选手比赛日程可直接求得//求解2个选手比赛日程,得到左上角元素a[1][1]=1; a[1][2]=2;

a[2][1]=2; a[2][2]=1;

for (t=1; t

//迭代处理,依次处理22, …, 2k个选手比赛日程 temp=n; n=n*2;

//填左下角元素 for (i=temp+1; i<=n; i++ )

for (j=1; j<=temp; j++)

a[i][j]=a[i-temp][j]+temp;

//左下角元素和左上角元素的对应关系 //填右上角元素 for (i=1; i<=temp; i++)

for (j=temp+1; j<=n; j++)

a[i][j]=a[i+temp][(j+temp)% n];

//填右下角元素 for (i=temp+1; i<=n; i++)

for (j=temp+1; j<=n; j++)

a[i][j]=a[i-temp][j-temp];

}

}

四、时间复杂度分析

迭代处理的循环体内部有3个循环语句,每个循环语句都是一个嵌套的for循环,且他们的执行次数相同,基本语句是最内层循环体的赋值语句,即填写比赛日程表中的元素。基本语句的执行次数是:

故其时间复杂性为O(4^k)。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值