网球循环赛 算法分析与设计(C++)
网球循环赛 算法分析与设计(C++)
设有n个运动员要进行网球循环赛。设计一个满足以下要求的比赛日程表:
1)每个选手必须与其他n-1个选手各赛一次
2)每个选手一天只能赛一次
3)当n是偶数时,循环赛进行n-1天。当n是奇数时,循环赛进行n天
书中对于 2 k 2^k 2k 的运动员的赛程安排在这里便行不通了,所以需要考虑新的办法。
如果当n为奇数时,可以考虑补充一个虚拟对手,即让n+1为偶数,多出的虚拟对手,代表轮空。
接下来考虑如果n/2为偶数,则可以同 2 k 2^k 2k一样的方法来进行填充,而如果n/2为奇数的话,需要进行新的处理。
综上,下面以n=6为例说明算法:
#define rep(i,s,n) for(int i=s;i<n;i++) //循环
void tournament(int n)
{if (n == 1){a[n][n] = 1;return;}if (n % 2 == 1)//奇数{tournament(n + 1);return;}tournament(n / 2);match_copy(n);}
主递归函数,先判断n是否为奇数,如果为奇数,则转换为求解n+1的问题
void match_copy(int n)
{if (n / 2 > 1 && odd(n / 2))copyodd(n);elsecopy(n);}
考虑n/2的奇偶性,分别做出处理
void copy(int n)
{int m = n / 2;for (int i = 1; i <= m; i++){for (int j = 1; j <= m; j++){a[i][j + m] = a[i][j] + m;a[i + m][j] = a[i][j + m];a[i + m][j + m] = a[i][j];/*rep(i, 1, 9) {rep(j, 1, 9){cout << a[i][j] << " ";}cout << endl;}*/}}}
该函数对n/2为偶数的情况进行处理。类似于书中的 2 k 2^k 2k的处理方式
具体操作过程是将n一分为2,通过一个正方形中左上角的值来得到其他三个角的值。
右上角的值=左上角值+m,右下角值=左上角值,左下角值=右上角值
以n=2为例:初始仅有一个1,但经过操作后可得到如下结果
1 | 2 |
---|---|
2 | 1 |
又如n=4:初始时仅有4个值,但是通过左右两次循环,上下两次循环 可以得到如下结果
1 | 2 | 1+2=3 | 2+2=4 |
---|---|---|---|
2 | 1 | 2+2=4 | 1+2=3 |
3 | 4 | 1 | 2 |
4 | 3 | 2 | 1 |
经过这样是可以解决n/2 为偶数的情况,现在再回到主递归函数,来从n=4生成n=6
void copyodd(int n)
{int m = n / 2;rep(i, 1, m + 1) {b[i] = m + i;b[m + i] = b[i];}rep(i, 1, m + 1){rep(j, 1, m + 2){if (a[i][j] > m){a[i][j] = b[i];a[m + i][j] = (b[i] + m) % n;}elsea[m + i][j] = a[i][j] + m;}rep(j, 2, m + 1){a[i][m + j] = b[i + j - 1];a[b[i + j - 1]][m + j] = i;}}
}
首先我们需要一个循环数组b,他是为了保证我们生成的后两列不会出现重复
比如我们这里的b为 4,5,6,4,5,6 很明显 第一行可以取4,5 第二行 取5,6 第三行取6,5,这样就正好补齐了前三行的后两列
接着我们通过以现有值叠加m的方式来得到后几行的结果,以第一行的值来确定第四行的值,第二行的值来确定第五行的值,第三行的值来确定第六行的值。
第一次循环:i=1 时,我们依次判断,通过第一个j循环可以得到以下结果
1 | 2 | 3 | 4 | ||
---|---|---|---|---|---|
2 | 1 | 4 | 3 | ||
3 | 4 | 1 | 2 | ||
1+3=4 | 2+3=5 | 3+3=6 | (4+3)%6=1 | ||
接下来进行下一个j循环,可以得到如下结果
1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|
2 | 1 | 4 | 3 | ||
3 | 4 | 1 | 2 | ||
4 | 5 | 6 | 1 | ||
1 | |||||
1 |
第二次循环:i=2时
1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|
2 | 1 | 4$\to$5 | 3 | ||
3 | 4 | 1 | 2 | ||
4 | 5 | 6 | 1 | ||
2+3=5 | 1+3=4 | (5+3)%6=2 | 3+3=6 | 1 | |
1 |
接下来进行下一个j循环,可以得到如下结果
1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|
2 | 1 | 5 | 3 | 6 | 4 |
3 | 4 | 1 | 2 | ||
4 | 5 | 6 | 1 | 2 | |
5 | 4 | 2 | 6 | 1 | |
2 | 1 |
第三次循环:i=3时
1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|
2 | 1 | 5 | 3 | 6 | 4 |
3 | 4 → 6 4\to6 4→6 | 1 | 2 | ||
4 | 5 | 6 | 1 | 2 | |
5 | 4 | 2 | 6 | 1 | |
3+3=6 | (6+3)%6=3 | 1+3=4 | 2+3=5 | 2 | 1 |
接下来进行下一个j循环,可以得到如下结果
1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|
2 | 1 | 5 | 3 | 6 | 4 |
3 | 6 6 6 | 1 | 2 | 4 | 5 |
4 | 5 | 6 | 1 | 3 | 2 |
5 | 4 | 2 | 6 | 1 | 3 |
6 | 3 | 4 | 5 | 2 | 1 |
综上我们就得到了n=6的情况,其具有一般代表性 如果n为奇数则加1,多出的一个选手代表轮空即可
算法分析:
T ( n ) = T ( n / 2 ) + O ( n 2 ) T(n)=T(n/2)+O(n^2) T(n)=T(n/2)+O(n2)
根据主定理可知 T ( n ) = O ( n 2 ) T(n)=O(n^2) T(n)=O(n2)
网球循环赛 算法分析与设计(C++)相关推荐
- 算法分析与设计——2.5 循环赛日程表
问题描述:设有n=个运动员要进行网球循环赛.现在要设计一个满足以下条件的比赛日程表. (1)每个选手必须要与其他n-1个选手各赛一次: (2) 每个选手一天只能赛一场: (3) 循环赛赛程是n-1 ...
- 网球循环赛赛程安排(分治策略)---附带详细代码
一.问题描述: 设有n个运动员要进行网球循环赛.设计一个满足以下要求的比赛日程表: (1)每个选手必须与其他n-1个选手各赛一次: (2)每个选手一天只能赛一次 ...
- c语言网球循环赛,网球循环赛比赛日程表n为奇数问题
初衷 在教材上看到这个问题的时候,对于奇数的处理百思不得其解,然而网上的答案要么就是n=2k的状况,要么就是本身根本都没有理解,给你讲了一大堆,各类状况,很麻烦,甚至有些是错的误人子弟.因此写下这篇思 ...
- 软件设计师-算法分析与设计
1.常用的算法设计方法: 1.1 迭代法 1.2 穷举搜索法 1.3 递推法 1.4 递归法 1.5 贪婪法 1.6 分治法 1.7 动态规划法 1.8 回溯法 算法 ...
- c语言-网球循环赛日程表
网球循环赛日程表 问题描述: 设有n个运动员要进行网球循环赛.设计一个满足以下要求的比赛日程表: (1)每个选手必须与其他n-1个选手各赛一次. (2)每个选手一天只能赛一次 (3)当n是偶数时循环赛 ...
- 《算法分析与设计》学习心得
在学习了<算法分析与设计>这门课后,我对常见的算法有了一个基本的了解.本书主要从算法概述.递归与分治策略.动态规划.贪心算法.回溯法.分支限界法.随机化算法.线性规划与网络流.NP完全性理 ...
- 基于C++的循环赛日程表算法设计
资源下载地址:https://download.csdn.net/download/sheziqiong/86806196 资源下载地址:https://download.csdn.net/downl ...
- 网球循环赛分治算法c语言,【算法作业】 循环赛问题 分治算法
题目: 设有N个运动员要进行网球循环赛,设计一个满足以下要求的比赛日程表 (1)每个选手必须与其他n-1个选手各赛一次 (2)每个选手一天只能赛一次 (3)当n是偶数,循环赛进行n-1天,当n是奇数, ...
- 程振波 算法设计与分析_算法分析与设计之动态规划
动态规划同样是一种将问题分解为求解子问题的方法,不过与分治不同的是,动态规划算法的子问题不是相互独立的,而是有公共的部分,即有重叠子问题,这个时候使用分治算法,将会重复计算公共的子问题,效率很低!而用 ...
最新文章
- 坑!只要年轻博士,薪资按考核结果发放, 高校的博后制度,究竟有多少门道?...
- CentOS 6.5/6.6 安装mysql 5.7 最完整版教程
- Github 代码上边的Raw、Blame、History是啥意思?
- debian linux 内核 3.14-1 显示器 很暗,Ubuntu 与 Linux Mint 用户安装 Kernel 3.14.1 内核
- 天津盈克斯机器人科技_柔性视觉选料 机器人摆盘 柔性振动盘
- 01-JVM与Java体系结构
- postgresql获取表最后更新时间(通过触发器将时间写入另外一张表)
- jquery之超简单的div显示和隐藏特效demo
- CDN/视频流成“风口”,2 年内实现规模商用,揭晓 2020 年边缘计算发展现状!...
- vs code 问题:preLaunchTask“build”已终止,退出代码为 1。解决办法
- restful levelsHATEOAS
- WebSocket 实现链接 群聊(low low low 版本)
- 【车牌识别】基于matlab GUI BP神经网络车牌识别【含Matlab源码 669期】
- XAMPP运行MySQL entire log window on the forums解决方案
- 虚拟机类加载机制(类加载过程)
- HDU 3713 Double Maze
- 2022年快手电商“大搞产业带”,如何抢跑快手电商下半场?
- 华为防火墙USG5500的配置方法
- Linux Ubuntu NFS 调试,Arm 挂载命令
- 网站结构优化要做好哪些