循环赛日程表分治递归求解
设计一个满足以下要求的比赛日程表:
(1)每个选手必须与其他n-1个选手各赛一次;
(2)每个选手一天只能赛一次;
(3)循环赛一共进行n-1天。
按分治策略,将所有的选手分为两半,n个选手的比赛日程表就可以通过为n/2个选手设计的比赛日程表来决定。递归地用对选手进行分割,直到只剩下2个选手时,比赛日程表的制定就变得很简单。这时只要让这2个选手进行比赛就可以了。
如上图,所列出的正方形表是8个选手的比赛日程表。其中左上角与左下角的两小块分别为选手1至选手4和选手5至选手8前3天的比赛日程。据此,将左上角小块中的所有数字按其相对位置抄到右下角,又将左下角小块中的所有数字按其相对位置抄到右上角,这样我们就分别安排好了选手1至选手4和选手5至选手8在后4天的比赛日程。依此思想容易将这个比赛日程表推广到具有任意多个选手的情形。
问题求解
(1)用一个for循环输出日程表的第一行 for(int i=1;i<=N;i++) a[1][i] = 1
(2)然后定义一个m值,m初始化为1,m用来控制每一次填充表格时i(i表示行)和j(j表示列)的起始填充位置。
(3)用一个for循环将问题分成几部分,对于k=3,n=8,将问题分成3大部分,
第一部分为,根据已经填充的第一行,填写第二行,
第二部分为,根据已经填充好的第一部分,填写第三四行,
第三部分为,根据已经填充好的前四行,填写最后四行。
可以用for (ints=1;s<=k;s++) N/=2; 描述这个过程
(4)用一个for循环对③中提到的每一部分进行划分for(int t=1;t<=N;t++)对于第一部分,将其划分为四个小的单元,即对第二行进行如下划分
同理,对第二部分(即三四行),划分为两部分,第三部分同理。
(5)最后,根据以上for循环对整体的划分和分治法的思想,进行每一个单元格的填充。填充原则是:对角线填充
for(int i=m+1;i<=2*m;i++) //i控制行 for(int j=m+1;j<=2*m;j++) //j控制列 { a[i][j+(t-1)*m*2]= a[i-m][j+(t-1)*m*2-m];
/*右下角的值等于左上角的值 */ a[i][j+(t-1)*m*2-m] =a[i-m][j+(t-1)*m*2];
/*左下角的值等于右上角的值 */}
算法实现
int a[101][101];
void cycle_table(int k)
{int n=1;//共有n个运动员for(int i=1;i<=k;i++) n=n*2;//先填写第一行for(int i=1;i<=n;i++) a[1][i]=i;int m=1;for(int s=1;s<=k;s++){n=n/2;//每次循环的次数for(int t=1;t<=n;t++)for(int i=m+1;i<=2*m;i++)for(int j=m+1;j<=2*m;j++){a[i][j+(t-1)*2*m]=a[i-m][j+(t-1)*2*m-m];a[i][j+(t-1)*2*m-m]=a[i-m][j+(t-1)*2*m];}m=m*2;}}
输入输出
输入
输入只有一行,输入一个数为k,运动员人数N=2k
输出
输出有N行N列,每个数字中间有一个空格
第一列表示每个运动员的序号,第2-N列表示N-1天的赛事安排
样例输入
3
样例输出
1 2 3 4 5 6 7 8
2 1 4 3 6 5 8 7
3 4 1 2 7 8 5 6
4 3 2 1 8 7 6 5
5 6 7 8 1 2 3 4
6 5 8 7 2 1 4 3
7 8 5 6 3 4 1 2
8 7 6 5 4 3 2 1
#include <iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
int a[101][101];
void cycle_table(int k)
{int n=1;//共有n个运动员for(int i=1;i<=k;i++) n=n*2;//先填写第一行for(int i=1;i<=n;i++) a[1][i]=i;int m=1;for(int s=1;s<=k;s++){n=n/2;//每次循环的次数for(int t=1;t<=n;t++)for(int i=m+1;i<=2*m;i++)for(int j=m+1;j<=2*m;j++){a[i][j+(t-1)*2*m]=a[i-m][j+(t-1)*2*m-m];a[i][j+(t-1)*2*m-m]=a[i-m][j+(t-1)*2*m];}m=m*2;}}
int main()
{int k;cin>>k;int n=1;for(int i=1;i<=k;i++) n=n*2;cycle_table(k);for(int i=1;i<=n;i++){for(int j=1;j<=n;j++)cout<<a[i][j]<<" ";cout<<endl;}return 0;
}
循环赛日程表分治递归求解相关推荐
- 循环赛日程表(递归法)
#include<iostream> #include<vector> #include<iterator> #include<algorithm> u ...
- 循环赛日程表 (递归与分治)
文章目录 1.题目 2.问题分析 3.什么是分治 4.算法实现思路 1.对表进行分析 2.对表的实现 1.递归 2.循环 5算法实现代码 1.递归 2.循环 6.时间\空间复杂度 1.递归 1.空间复 ...
- 3.2.4循环赛日程表(递归与分治)
目录 1.问题描述 2.算法分析 算法 3.摘要 参考书籍 1.问题描述 设有个运动员要进行网球循环赛. 现要设计一个满足以下要求的比赛日程表. (1)每个选手必须与其他个选手各比赛一次: (2)每个 ...
- 循环赛日程表非递归Java_王晓东《算法设计与分析》课件.ppt
<王晓东<算法设计与分析>课件.ppt>由会员分享,可在线阅读,更多相关<王晓东<算法设计与分析>课件.ppt(356页珍藏版)>请在人人文库网上搜索. ...
- 任意人数的循环赛日程表 分治 非分治 c++
循环赛日程表 要求 设计一个满足以下要求的比赛日程表: 每个选手必须与其他n-1个选手各赛一次: 每个选手一天只能赛一次: 当n是偶数时,循环赛进行n-1天,当n是奇数时,循环赛进行n天: 举例 4位 ...
- 循环赛日程表 分治(超详细注释!!!)
设有n=2k个运动员要进行网球循环赛.现要设计一个满足以下要求的比赛日程表: (1)每个选手必须与其他n-1个选手各赛一次: (2)每个选手一天只能赛一次: (3)循环赛一共进行n-1天. answe ...
- c语言 循环赛日程表 n=2^k,循环赛日程表分治算法(c语言)
/* * 设有n=2k个运动员要进行网球循环赛.现要设计一个满足以下要求的比赛日程表: * 每个选手必须与其他n-1个选手各赛一次: * 每个选手一天只能参赛一次: * 循环赛在n-1天内结束. * ...
- 循环赛日程表------分治算法
[题目描述] 设有NN个选手进行循环比赛,其中N=2M2M,要求每名选手要与其他N−1N−1名选手都赛一次,每名选手每天比赛一次,循环赛共进行N−1N−1天,要求每天没有选手轮空. [输入] 输入:M ...
- c 最大子序列和_最大子序列和暴力法、分治+递归法、妙法
你好,我是goldsunC 让我们一起进步吧! 最大子序列和 Question:给定整数(可能有负数),求的最大值(为方便起见,如果所有整数均为负数,则最大子序列和为0). 示例: IN : [-2, ...
最新文章
- memcacheq 服务安装与原理
- 关于ShapeDrawable应用的一些介绍(下)
- Python爬虫 解析库的使用
- sklearn自学指南(part4)--使用手册的目录
- 做一个项目,平时都用到哪些工具提高效率(中)
- 数据库的设计与连接、站点的搭建
- 策略设计模式_设计模式之策略模式总结
- 记工软件 包工头记工软件 建筑记工软件 工程记工软件
- php批量修改怎么实现,PinPHP购物分享系统2.2后台批量采集修改实现方法
- 联想无线网卡 linux驱动,联想R7000 Ubuntu无线网卡驱动
- 分析内网即时通讯软件安全性如何
- 【哈希链表】 146 LRU、LFU缓存机制
- 2020中国云计算行业研究报告 附下载地址
- Node项目实战总结
- ubuntu使用certbot给nginx添加ssl证书
- 一个定语修饰两个并列的名词。
- Android 用 broadcast receiver组件实现音乐盒
- 阿里云服务器证书登录如何配置
- R语言计算多变量两两之间的相关关系及显著性
- linux强制网卡linkup,使用ip link set eth0 up 命令启用网卡后,网络不通的问题的解决...