循环赛日程表分治算法(c语言)
网球循环赛日程表

一、问题表述:设有n个运动员要进行网球循环赛。
设计一个满足以下要求的比赛日程表,(1) 每个选手必须与其他n-1个选手各赛一次;(2) 每个选手一天只能赛一次;(3) 当n是偶数时,循环赛进行n-1天,当n是奇数时,循环赛进行n天二、分析问题题目是要n名运动员进行循环比赛。
当n为偶数时,正好每天都可以两两一组,与其余的n-1个选手比赛,只需n-1天;而当n为奇数,每天将有一个选手轮空,比赛将持续n天。
可以采用的算法如下:1.算法一:使用分治法当n为偶数时,可以讲问题分为两个部分n/2; 然后继续划分,知道最后剩余两名选手单独比赛。
当n为奇数时,增设一个虚拟选手,运动员为n+1个,将问题转化为是偶数的情形。
当选手与虚拟选手比赛时,表示轮空,因此只需要关注n为偶数的情形。
a)当n/2为偶数时,与n = 2^k情形类此。
b)当n/2为奇数时,增设一个虚拟的选手,递归返回的将有轮空的选手,可以讲在前面n/2轮比赛的选手与后面n/2轮空的选手进行比赛。
2.算法二:利用边是奇数的正多边形。
特点:以多边形中的任意一个顶点画对称轴,其余偶数对顶点相互对称。
N名选手编号为1~n,将其画成一个正多边形。
a)所以当n为奇数时,第一天1号休息,其余以一号为对称轴,两两对称打比赛,第二天开始一次轮流休息,其余一休息的那个人编号为对称轴,两两比赛。
这样比赛可进行n天。
如图:12345678012345678对称轴此时n=9,为奇数,从0开始每天有一个人轮空对称轴b) 当n 为偶数时,取出编号最大的,其他的组成一个正多边形,n 号一次顺序与1,2,。
n -1号选手比赛,其他与a )相同。
如图所示:(图中是从0开始编号)123456789 9N=2k 时9三、 理论分析算法及实现1. 算法一:使用分治法a) 算法的思路:按分治策略,可以将所有的选手对分为两组(如果n 是偶数,则直接分为n/2每组,如果n 是奇数,则取(n+1)/2每组),n 个选手的比赛日程表就可以通过为(n/2或(n+1)/2)个选手设计的比赛日程表来决定。
用C++编写循环赛日程表

循环赛日程表问题描述:设有n位选手参加网球循环赛,n=2^k,循环赛共进行n-1天,每位选手要与其他n-1位选手比赛一场,且每位选手每天比赛一场,不能轮空,按一下要求为比赛安排日程,(1)每位选手必须与其他n-1格选手格赛一场;(2)每个选手每天只能赛一场;(3)循环赛一共进行n-1天;#include<iostream.h>int a[50][50];void table (int x,int k)//此函数为从x号球员起的共2的k次方名球员的安排日程表{int i,j,y=1;if(k==1)//只有两名球员{a[x][0]=x;a[x][1]=x+1;a[x+1][0]=x+1;a[x+1][1]=x;}else{for(i=1;i<=k-1;i++){y=y*2;}table(x,k-1);table(x+y,k-1);for(i=x;i<x+y;i++){for(j=y;j<2*y;j++)a[i][j]=a[i+y][j-y];}for(i=x+y;i<x+2*y;i++){for(j=y;j<2*y;j++)a[i][j]=a[i-y][j-y];}}}void main(){int i,j,k;int n=1;cout<<"请输入k值"<<endl;cin>>k;for(i=1;i<=k;i++){n=n*2;}cout<<"参赛人数"<<" "<<n<<endl; table(1,k);cout<<"*****循环赛日程表****"<<endl;cout<<endl;cout<<"日期:";for( i=1;i<n;i++)cout<<" "<<i;cout<<endl;for(i=1;i<n;i++){cout<<endl;for(j=1;j<n;j++)cout<<" "<<a[i][j]<<" ";}cout<<endl;}执行结果如下:。
循环赛日程表问题研究

循环赛日程表问题研究题目循环赛日程表问题研究学生指导教师年级 2009级专业软件工程系别软件工程学院计算机科学与信息工程学院哈尔滨师范大学2012年6月论文提要本文采用分治算法来解决循环赛日程表的安排问题。
通过对问题的详细分析,列出1到10个选手的比赛日程表,找出两条规则,作为算法实现的依据,而后采用c语言实现算法,通过测试分析,程序运行结果正确,运行效率较高。
同时也介绍了循环赛日程表问题的另一种解法多边形解法,这种方法另辟蹊径,巧妙地解决了循环赛日程表问题,运行效率较高。
循环赛日程表问题研究摘要:本文采用分治算法来解决循环赛日程表的安排问题。
根据算法的设计结果,采2用c语言实现算法,通过测试分析,程序运行结果正确,运行效率较高。
同时也介绍了循环赛日程表问题的另一种解法,这种方法另辟蹊径,想法独特,运行效率较高。
关键词:循环赛日程表问题,分治法一、题目描述设有n个运动员要进行网球循环赛。
设计一个满足以下要求的比赛日程表:(1)每个选手必须与其他n-1个选手各赛一次;(2)每个选手一天只能赛一次;(3)当n是偶数时,循环赛进行n-1天。
当n是奇数时,循环赛进行n天。
二、问题分析循环赛日程表可以采用分治法实现,把一个表格分成4个小表格来处理,每个小表格都是一样的处理方法,只是参数不同。
分析过程具体如下:1、n=1(表2-1)12.、n=2-2) (表21 22 13、n=3(1) 添加一个虚拟选手4#,构成n+1,4(2) 4/2,2,分两组,每组各自安排(1 2),(3 4)(3) 每组跟另一组分别比赛(拷贝)这是四个人比赛的(表2-3) 4人赛程1 2 3 42 1 4 33 4 1 24 3 2 1 (4) 把虚选手置为0(表2-4)3人赛程31 2 3 02 1 0 33 0 1 20 3 2 1这是三个人比赛的安排4、n=4,见表2-35、n=5(1) 加一个虚选手,n+1=6。
安排好6个人的比赛后,把第6个人用0表示即得5人的。
循环赛日程表问题

7
8
2013-6-1
8
7
5
6
6
5
2
4
4
3
1
2
2
1
6/9
程序实现
v o i d t a s t a r t , i { i f ( s t a r t < i n t + 1 ; i f ( { b l e ( i n t * n t e n d ) s t a r t > = = 0 ) r e t第 u 选 手 n = e n d一 天 n = = 2 )
a [ s t a r t 3] [ 1 1] 4 2
=7
a [ s t a r t 5+ 1 ] 7[ 1 ] 1 = 6
m i d =
7
8
5
6
6
5
2
4
4
3
1
2
2
1
7/9
2013-6-1
( e n d
+
程序实现
p y ( i n t e s t a r = 0 ) n = = n m i d 2 ; ( i n t ; i < = f o ; j + + { a [ i - m ] [ j - m ] } 2013-6-1 v o i d c o s t a r t , i { i f ( s t a r t < i n t 1 ; i n t m i n t s t a r t ) / f o r i = m i d + 1 { j = m ; j < n n t * * a , i n图示 t 隐藏 n d ) t > = e n d | | r e t u r n ; 第 e n d 选 - 第 s t 第 r t第 第 a 第 + 一 二 三 四 五 六 手 / 2 ; 天 天 天 天 天 天 = ( e n 2d 3 + 4 5 6 7 1
分治算法经典问题算法:循环赛程表,归并排序,快速排序,二分搜索,二分递归,大数乘法,棋盘覆盖

循环赛程表#define MAXN 64#define MAX 32int a[MAX][MAX];void Copy(int tox, int toy, int fromx, int fromy, int n) { for (int i=0; i<n; i++)for (int j=0; j<n; j++)a[tox + i][toy + j] = a[fromx + i][fromy + j];}void Table(int k, int a[][MAX]){ int i, n = 1 << k;int r;for (i=0; i<n; i++)a[0][i] = i + 1;for (r=1; r<n; r<<=1){ for (i=0; i<n; i+=2*r){ Copy(r, i + r, 0, i, r);Copy(r, i, 0, i + r, r);}}//ENDFOR}void Out(int a[][MAX], int n){ for (int i=0; i<n; i++){ for (int j=0; j<n; j++) printf("%3d", a[i][j]);printf("\n");}printf("\n");getch();}void main(){ int i;for (i=0; i<5; i++){ int len = 1 << i;Table(i, a);Out(a, len);}}归并排序void merge(int data[], int p, int q, int r){ int n1 = q - p + 1;int n2 = r - q;int L[n1],R[n2];for(int i = 0, k = p; i < n1; i++, k++) L[i] = data[k];for(int i = 0, k = q + 1; i < n2; i++, k++) R[i] = data[k];for(int k = p, i = 0, j = 0; i < n1 && j < n2; k++){ if(L[i] > R[j]) { data[k] = L[i]; i++; }else { data[k] = R[j]; j++; }}if(i < n1) { for(j = i; j < n1; j++, k++) data[k] = L[j]; }if(j < n2) { for(i = j; i < n2; i++, k++) data[k] = R[i]; }}void merge_sort(int data[], int p, int r){ if(p < r){ int q = (p + r) / 2;merge_sort(data, p, q);merge_sort(data, q + 1, r);merge(data, p, q, r);}}快速排序int partition(int number[], int left, int right){ int s = number[right];int i = left - 1;for(int j = left; j < right; j++)if(number[j] <= s) { i++; SW AP(number[i], number[j]); } SW AP( number[i+1], number[right] );return i+1;}void quicksort(int number[], int left, int right){ int q;if(left < right){ q = partition(number, left, right);quicksort(number, left, q-1);quicksort(number, q+1, right);}}二分搜索(非递归)public static int binarySearch(int [] a, int x, int n){ // 在a[0] <= a[1] <= ... <= a[n-1] 中搜索x// 找到x时返回其在数组中的位置,否则返回-1int left = 0; int right = n - 1;while (left <= right){ int mid = (left + right)/2; // mid = low + ((high - low) / 2);if (x == a[mid]) return mid;if (x > a[mid]) left = mid + 1;else right = mid - 1;}return -1; // 未找到x}二分递归public static int binarySearch(int a[], int x, int left ,int right){ // 找到x时返回其在数组中的位置,否则返回-1if (left>right) return -1; // 未找到xelse{ int mid = (left + right)/2;if (x == a[mid]) return mid;if (x > a[mid]) return binarySearch(a, x, mid+1,right);else return binarySearch( a,x,left,mid);}}大数乘法int qiuweishu(long z){ int t=0;while(z>0){ z=z/10; t++; }return t;}main(){ long x,y,a,b,c,d;double z;printf("Please input the two number x and y:\n");scanf("%,%l",&x,&y);a=x/(long)pow10(qiuweishu(x)/2);b=x%(long)pow10(qiuweishu(x)/2);c=y/(long)pow10(qiuweishu(y)/2);d=y%(long)pow10(qiuweishu(y)/2);z=(double)(a*c*pow10(qiuweishu(x))+(a*d+b*c)*pow10(qiuweishu(x)/2)+b*d); /*z=(a*c*(long)pow10(qiuweishu(x))+((a-b)*(d-c)+a*c+b*d)*(long)pow10(qiuw eishu(x)/2)+b*d);*/printf("the result is %ld:",z);}棋盘覆盖#define BOARD_SIZE 4int board[BOARD_SIZE][BOARD_SIZE];// c1, r1: 棋盘左上角的行号和列号c2, r2: 特殊方格的行号和列号void chessboard(int r1, int c1, int r2, int c2, int size) // size = 2 ^ k{ if(1 == size) return;int half_size;static int domino_num = 1;int d = domino_num++;half_size = size / 2;if(r2 < r1 + half_size && c2 < c1 + half_size) //特殊方格在左上角子棋盘{ chessboard(r1, c1, r2, c2, half_size); }else // 不在此棋盘,将此棋盘右下角设为相应的骨牌号{ board[r1 + half_size - 1][c1 + half_size - 1] = d;chessboard(r1, c1, r1 + half_size - 1, c1 + half_size - 1, half_size);}if(r2 < r1 + half_size && c2 >= c1 + half_size) //特殊方格在右上角子棋盘{chessboard(r1, c1 + half_size, r2, c2, half_size); }else // 不在此棋盘,将此棋盘左下角设为相应的骨牌号{ board[r1 + half_size - 1][c1 + half_size] = d;chessboard(r1, c1 + half_size, r1 + half_size - 1, c1 + half_size, half_size);}if(r2 >= r1 + half_size && c2 < c1 + half_size) //特殊方格在左下角子棋盘{ chessboard(r1 + half_size, c1, r2, c2, half_size);}else // 不在此棋盘,将此棋盘右上角设为相应的骨牌号{ board[r1 + half_size][c1 + half_size - 1] = d;chessboard(r1 + half_size, c1, r1 + half_size, c1 + half_size - 1, half_size);}if(r2 >= r1 + half_size && c2 >= c1 + half_size) //特殊方格在左上角子棋盘{chessboard(r1 + half_size, c1 + half_size, r2, c2, half_size); }else // 不在此棋盘,将此棋盘左上角设为相应的骨牌号{ board[r1 + half_size][c1 + half_size] = d;chessboard(r1 + half_size, c1 + half_size, r1 + half_size, c1 + half_size, half_size);}}//ENDint main(){ board[2][2] = 0;chessboard(0, 0, 2, 2, BOARD_SIZE);for(i = 0; i < BOARD_SIZE; i++){for(j = 0; j < BOARD_SIZE; j++){printf("%-4d", board[i][j]);}printf("\n");}}。
分治法在循环赛日程表设计中的应用

比赛日程表来决定。递归地执行这种分割,直到只剩下 2 个选手 比赛。
时,比赛日程表的制定就变得很简单:只要让这 2 个选手进行比
算法如下:
赛就可以了。再逐步合并子问题的解即可得到原问题的解。
void tourna(int n) //改进的分治赛算法
算法如下:
{
void tourna(int n)
//基本的分治算法
void copy(int n)
思想是,将一个难以直接解决的大问题,分割成一些规模较小的
{
相同问题,以便各个击破,分而治之。但是不是所有问题都适合
int m=n/2;
用分治法解决。当求解一个输入规模为 n 且取值又相当大的问
for(int i=0;i<m;i++)
题时,使用蛮力策略效率一般得不到保证。
}
45
分析算法的时间性能,迭代处理的循环体内部有 2 个循环
采用分治算法解决问题的基本步骤为:
语句,基本语句是最内层循环体的赋值语句,即填写比赛日程表
(10 分解:将原问题分解为若干个规模较小,相互独立,与原 问题形式相同的子问题;
(2)求解子问题:若子问题规模较小而容易被解决则直接解, 否则再继续分解为更小的子问题,直到容易解决;
(3)合并:将已求解的各个子问题的解,合并为原问题的解。 需要注意的是,不是所有的分治法都比简单的蛮力法更有效。
2 循环赛分治算法
下面,我们应用分治法解决循环赛日程表的设计问题。 2.1 问题描述 有 n 支球队参加循环赛,设计一个满足下面要求的比赛日 程表: (1)每支球队必须与其他 n-1 支球队各赛一次; (2)每支球队一天只能比赛一次; (3)当 n 为偶数时,比赛进行 n-1 天;当 n 为奇数时,比赛进 行 n 天。 按此要求,可将比赛日程表设计成一个 n 行 n 列的二维表。 2.2 算法分析 当 n=2(k k=1、2、3、4,……,n=2、4、8、16,……)时,此时问题 比较简单。按照分治的策略,可将所有参赛的选手分为两部分,
循环赛日程表

算法设计与分析实验报告循环赛日程表一.问题描述设有n位选手参加循环赛,设计循环赛日程表,要求:每位选手必须和其余n-1个选手比赛;每位选手每天只能比一场比赛;若n为奇数,则比赛n天;若n为偶数,则比赛n-1天。
二.实验目的熟悉分治法的思想并掌握其运用。
三.实现方式编译环境:Dev-C++算法思路:使用分治法的思想,给n个选手安排日程表转化为给n/2个选手安排日程表,直到问题规模变成给两个选手安排日程。
日程表可以用一个二维数组表示,数组的大小为k (n<=2^k),第i行第j列的数组值表示第i个选手在第j-1天比赛的对手(第1列表示选手的编号,假定选手的编号为1,2,3…恰为数组的行数)。
划分:n个选手的日程表可以由n/2个选手的日程表合并而得。
解决:当只有两个选手比赛的时候,可以直接给出其日程表,得到一个2×2的数组。
当有4个选手参加比赛的时候,则将两个2×2的数组合并,得到一个4×4的数组。
以此类推,n 个选手的日程表由n-1个选手的日程表合并而成。
合并规则为:若n 为偶数,则会得到一个n ×n 的表格;若n 为奇数,需要比赛n 天,则会得到一个n ×(n+1)的表格且每一天必定有一位选手轮空。
因此在合并的时候要先把表格扩充为(n+1)×(n+1)的表格,然后再消除虚拟的选手(用0表示轮空)。
例:n=3时赛程表为:当n=6时,将两个n=3的赛程表合并,在同一天轮空的选手便可在该天比赛。
然后再补上表格右边的元素。
设当前要合并的数组的长度为s,表格左下角的元素可由左上角的元素+s而得:表格右上角的元素由前一行决定:表格右下角的元素由表格右上角对应元素所决定:四.结果验证(1)调用函数IsRight()可验证所得结果的正确性(即每行,每列没有相同的元素),若结果可行,则返回1;否则返回0;(2)调用DoTest()函数可以把2~N(N用const定义为一个常量,可随时修改)个选手的赛程表作为数据集写到文件RoundMatch中。
循环赛问题分析与C语言代码-分治法

问题描述:设有n个运动员要进行网球循环赛。
设计一个满足以下要求的比赛日程表:(1)每个选手必须与其他n-1个选手各赛一次;(2)每个选手一天只能赛一次;(3)当n是偶数时,循环赛进行n-1天。
当n是奇数时,循环赛进行n天。
分析过程:这个问题的解搜索空间是一个n的全排列。
要求的解是其中的n个排列,满足条件:第1列n个元素值按增序排列;每行每列没有相同的数。
也是一个幻方(除对角线的和不作要求)的问题。
1.n=11)2. n=2(表2)3.n=3,(1) 添加一个虚拟选手4#,构成n+1=4(2) 4/2=2,分两组,每组各自安排(1 2),(3 4)(3)每组跟另一组分别比赛(拷贝)这是四个人比赛的安排(4)把虚选手置为0(表4)3人赛程这是三个人比赛的安排4. n=4, 见表35. n=5, (1)加一个虚选手,n+1=6。
安排好6个人的比赛后,把第6个人用0表示即得5人的。
(2) 分成两组(1 2 3) (4 5 6),各3名选手(3) 依照表4,安排第1组;按表5安排第2组(除0元素外,都加3)(表5)(4) 把表5排于表4下方(5) 把同一天都有空的两组安排在一起比赛(按这种安排,肯定每天只有一对空组,?)。
(6) 第一组的(1 2 3)和第2组的(4 5 6)分别比赛。
但是由于(1,4), (2, 5), (3 6)已经比赛过了,所以在后面的安排中不能再安排他们比赛。
1 2 34 5 6首先,1#只能和5#或6#比赛。
(a)若1#-5#,由于3#和6#已经比赛过,所以只能安排: 2#-6#,3#-4#(b)若1#-6#,由于2#和5#已经比赛过,只能安排:2#-4#,3#-5#这样安排后前三行的后两列,后三行的后两列由上面的三行来定:表8就是6名选手的比赛日程安排。
将其中的6号作为虚拟选手,把6换成0,即得5名选手的赛程安排表:(表9)5人赛程6 n=6,见表8。
7 n=7, 添加1,n+1=8。
利用分治法设计循环赛日程表

利用分治法设计循环赛日程表作者:王猛来源:《科技经济市场》2008年第07期摘要:对于单循环赛的比赛日程安排问题,利用分治算法给出了可读性较好的设计,并分析了各种假设下的时间复杂度。
关键词:分治算法;复杂度;递归;循环赛引言任何一个可以用计算机求解的问题所需的计算时间都与其规模有关。
问题的规模越小,越容易求解,所需的计算时间也越少。
分治法是计算机科学中经常使用的一种算法。
设计思想是,将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。
1分治法应用条件及一般步骤1.1 分治法的应用条件1.1.1能将n个数据分解成k个不同子集合,且得到的k个子集合是可以独立求解的子问题,其中11.1.2分解所得到的子问题与原问题具有相似的结构,便于利用递归或循环机制;1.1.3合并各个子问题的解,就是原问题的解。
1.2 分治法的一般步骤1.2.1分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题;1.2.2求解子问题:若子问题规模较小而容易解决则直接解,否则再继续分解为更小的子问题,直到容易解决;1.2.3合并:将已求解的各个子问题的解,合并为原问题的解。
2 循环赛分治算法2.1 问题描述有n支球队参加循环赛,设计一个满足下面要求的比赛日程表:2.1.1每支球队必须与其他n-1支球队各赛一次;2.1.2每支球队一天只能比赛一次;2.1.3当n为偶数时,比赛进行n-1天;当n为奇数时,比赛进行n天。
2.2 算法分析当n=2k (k=1、2、3、4……)时,比较简单。
按照分治的策略,可将所有参赛的选手分为两部分,n=2k 个选手的比赛日程表就可以通过为n/2=2k-1 个选手设计的比赛日程表来决定。
递归地执行这种分割,直到只剩下2个选手时,比赛日程表的制定就变得很简单,只要让这2个选手进行比赛就可以了。
再逐步合并子问题的解即可得到原问题的解。
算法如下:void tourna(int n){if(n==1){a[0][0]=1;return;}tourna(n/2);copy(n);}void copy(int n){int m=n/2;for(int i=0;ifor(int j=0;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];}基本语句的执行次数是:T(n)=3=O(4k ),所以算法的时间复杂度为O( 4k)。
分治法循环赛日程表实验报告

西北农林科技大学信息工程学院《算法分析与设计》综合训练实习报告题目:分治法循环赛日程表学号姓名专业班级指导教师实践日期2011年5月16日-5月20日目录一、综合训练目的与要求 (1)二、综合训练任务描述 (1)三、算法设计 (1)四、详细设计及说明 (3)五、调试与测试 (4)六、实习日志 (6)七、实习总结 (6)八、附录:核心代码清单 (6)一、综合训练目的与要求本综合训练是软件工程专业重要的实践性环节之一,是在学生学习完《算法分析》课程后进行的综合练习。
本课综合训练的目的和任务:(1)巩固和加深学生对算法分析课程基本知识的理解和掌握;(2)培养利用算法知识解决实际问题的能力;(3)掌握利用程序设计语言进行算法程序的开发、调试、测试的能力;(4)掌握书写算法设计说明文档的能力;(5)提高综合运用算法、程序设计语言、数据结构知识的能力。
二、综合训练任务描述假设有n=2k 个运动员要进行网球循环赛。
设计一个满足一下要求的比赛日程表:(1)每个选手必须与其他n-1个选手各赛一次(2)每个选手一天只能赛一次(3)循环赛一共进行n-1天利用Java语言开发一个界面,输入运动员的个数,输出比赛日程表。
对于输入运动员数目不满足n=2k时,弹出信息提示用户。
三、算法设计(1) 文字描述假设n位选手顺序编号为1,2,3……n,比赛的日程表是一个n行n-1列的表格。
第i行j列表示第i号选手在第j天的比赛对手,根据分治法,要求n个选手的比赛日程,只要知道其中一半的比赛日程,所以使用递归最终可以分到计算两位选手的比赛日程,然后逐级合并,得出结果。
(2) 框图图 1(3) 伪代码static int a[][] = new int[100][100];static int athletes;static int n;static 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];// 把左上角数的值赋给对应的右下角数}}static void tournament(int n) // 分治算法,递归调用自己{if (n == 1) {a[1][1] = 1;return;}tournament(n / 2); // 分治copy(n); // 合并}public static void main(String[] args) {n=getText();athletes = n;tournament(n);}}四、详细设计及说明(1)输入一个数字n,根据(x&(x-1))==0判断n是否等于2^k。
分治法——循环赛日程表

分治法——循环赛⽇程表1、问题描述:有n=2^k个远动员选⼿,设计⽐赛⽇程表实现:(1)每个选⼿必须与n-1个选⼿⽐赛(2)每个选⼿⼀天只⽐赛⼀场(3)⽐赛共进⾏n-1天输⼊:n⼈输出:n⾏n-1列,第i⾏第j列表⽰第i个选⼿第j天遇到的对⼿,不包含第⼀列表⽰为选⼿编号举例:2⼈1 22 12、问题分析通过化⼤为⼩,分⽽治之的思想,将多⼈的⽐赛⽇程缩⼩为2⼈的⽇程。
以此倒推所有⼈的⽇程。
注意多⼈⽇程规律:以四⼈为例:1 2 | 3 42 1 | 4 3----------3 4 | 1 24 3 | 2 1这样⼀个矩阵分为四个区,左上和右下⼀样,左下和右上⼀样,且右上是左上对应的数字加了n/2.3、代码实现1 #include <stdio.h>2 #include <string.h>34#define N 1285int matrix[N][N] = {0};67void fun(int n)8 {9int i;10int j;11if (n<=0)12 {13return;14 }15if (n>2)16 {17 fun(n/2);18for (i=1;i<=n/2;i++)19 {20for (j=n/2+1;j<=n;j++)21 {22 matrix[i][j] = matrix[i][j-n/2] + n/2;23 }24 }25for (i=n/2+1;i<=n;i++)26 {27for (j=1;j<=n/2;j++)28 {29 matrix[i][j] = matrix[i-n/2][j+n/2];30 }31 }32for (i=n/2+1;i<=n;i++)33 {34for (j=n/2+1;j<=n;j++)35 {36 matrix[i][j] = matrix[i-n/2][j-n/2];37 }38 }39 }40else41 {42 matrix[1][1] = 1;43 matrix[1][2] = 2;44 matrix[2][1] = 2;45 matrix[2][2] = 1;46 }47 }4849void main()50 {51 fun(8);5253int i,j;54for (i=1;i<=8;i++)55 {56for (j=1; j<=8; j++)57 {58 printf("%d ",matrix[i][j]);59 }60 printf("\n");61 }62 }。
要求:编写程序,用分治法求解循环赛日程表。

要求:编写程序,用分治法求解循环赛日程表。
一、实验目的与要求1、掌握网球循环赛日程表的算法;2、初步掌握分治算法二、实验题:问题描述:有n=2^k个运动员要进行循环赛。
现要设计一个满足以下要求的比赛日程表:(1)每个选手必须与其他n-1个选手各赛一次(2)每个选手一天只能赛一次(3)循环赛一共进行n-1天三、实验代码#include <stdio.h>#include <stdlib.h>#define MAX 1024int a[MAX][MAX];void Copy(int tox, int toy, int fromx, int fromy, int n){ int i, j;for (i=0; i<n; i++){ for (j=0; j<n; j++){ a[tox + i][toy + j] = a[fromx + i][fromy + j];}}}void Table(int k, int a[][MAX]){ int i, n = 1 << k;for (i=0; i<n; i++){ a[0][i] = i + 1;}for (int r=1; r<n; r<<=1){ for (i=0; i<n; i+=2*r){ Copy(r, i + r, 0, i, r);Copy(r, i, 0, i + r, r);}}}void Out(int a[][MAX], int n){ int i, j;for (i=0; i<n; i++){ for (j=0; j<n; j++){ printf("%3d", a[i][j]);} printf("\n");} printf("\n");}int main(){ int i;for (i=0; i<5; i++){ int len = 1 << i;Table(i, a);Out(a, len);} return 0;}四、实验结果。
利用分治法设计循环赛日程表

} voi d ma kee opy ( i n t m
{遗( rl /2) >1&&odd∽))c opyodd( n);
els e c opy( n); l voi d eop yodd ( i nt n) {i n t m=n/2; f or ( int i- -O;i<m;i ++)
el se a[m+i 】【j 】-a 【i 】【j 】+m; l f or O=l ;j <m;j ++) {a [i l[m+j 】- b[ i+j 】; a【b“+j 】Ⅱm+j 】- i ; }
l 1
分析算法的 时间性能: 当n/2为 奇数时,基本 语句的执行次 数是:
T∞=∑2+∑( ∑+∑2) =0( 42)
算法如下: voi d t o uma( i nt n) {if ( n==1) {a[ O][ 0]=1;r et urn;J tour ed(n/2); copy( n); J voi d copy( hat I n {i n t re =n /2 ;
f or (hat i -- O;i <m;i ++) f or (i nt j =0.j<玎嘶++)
随着计算机技术的蓬勃发展计算机教学将面临新的挑战机房管理也将越来越受到学校的重视在以后的工作中机房管理人员应不断总结积累经验提高工作效率提高自身的管理水平和技术水平更好地为学校教育教学服务
煎垫壅进查塑
÷
…}
ቤተ መጻሕፍቲ ባይዱ
垫查±鱼
利用分治法设计 循环赛日程表
循环赛日程表问题

5
4
3
2
7
6
10*
8
2
9
1
5
4
3
8
3
6
7
9
10*
2
1
5
4
9
10*
4
6
8
7
3
2
1
5
10*
9
7
5
6
8
4
3
2
1
当n=9/10时,规则同上(n=9时用一位虚拟选手补全)
总结:
观察右上角灰色部分可知:【规则一】:每一行数值从左到右循环递增; 每一列上也是6~10循环递增; 第一行第m+1(下标从0开始)列的值为(m+1)+1,依次向右递增;【规则二】:右下角的块:因为比赛是两两之间进行的,所以右下角由右上角决定。
代码实现
代码实现
运行结果
循环赛日程表
/9
内容简介
问题描述
A
解题思路
B
程序实现
C
知识延伸
D
问题描述:设有n(n = 2k)位选手参加网球循环赛,循环赛共进行n-1天,每位选手要与其他n-1位选手比赛一场,且每位选手每天必须比赛一场,不能轮空。每个选手必须与其他n-1个选手各赛一场;每个选手一天只能赛一场。
问题描述
解题思路
采用分治法实现,把一个表格分成4个小表格来处理,每个小表格都是一样的处理方法,只是参数不同。分析过程具体如下:
n=1
n=2
选手
第一天
1
1
2
2
1
n=3
n=4
选手
第一天
第二天
第三天
循环赛问题分析与C语言代码分治法

7
8
9
6
7
8
9
0
1
5
4
3
2
7
6
0
8
2
9
1
5
4
3
8
3
6
7
9
0
2
1
5
4
9
0
4
6
8
7
3
2
1
5
0
9
7
5
6
8
4
3
2
1
由上面的分析,可以总结出如下算法:
n名选手的赛程安排问题:
1如果n为偶数,可分为两个n/2人的组,分别比赛,然后两组间比赛。
1.1如果n/2为偶数,左下角为左上角加n/2来得到,然后左下角拷贝到右上角;左上角拷贝到右下角;
6
0
4
5
0
3
2
1
(4)把表5排于表4下方
(表6)
1
2
3
0
2
1
0
3
3
0
1
2
4
5
6
0
5
4
0
6
6
0
4
5
(5)把同一天都有空的两组安排在一起比赛(按这种安排,肯定每天只有一对空组,?)。
(表7)
1
2
3
4
2
1
5
3
3
6
1
2
4
5
6
1
5
4
2
6
6
3
4
5
(6)第一组的(1 2 3)和第2组的(4 5 6)分别比赛。但是由于(1,4), (2, 5), (3 6)已经比赛过了,所以在后面的安排中不能再安排他们比赛。
算法分析思维分析,以循环赛日程表为例

算法分析思维分析,以循环赛⽇程表为例第⼀步:分治法的简单思想在计算机科学中,分治法是⼀种很重要的算法。
字⾯上的解释是“分⽽治之”,就是把⼀个复杂的问题分成两个或更多的相同或相似的⼦问题,再把⼦问题分成更⼩的⼦问题……直到最后⼦问题可以简单的直接求解,原问题的解即⼦问题的解的合并。
这个技巧是很多⾼效算法的基础,如排序算法(,归并排序),傅⽴叶变换()等等。
任何⼀个可以⽤计算机求解的问题所需的计算时间都与其规模有关。
问题的规模越⼩,越容易直接求解,解题所需的计算时间也越少。
例如,对于n个元素的排序问题,当n=1时,不需任何计算。
n=2时,只要作⼀次⽐较即可排好序。
n=3时只要作3次⽐较即可,…。
⽽当n较⼤时,问题就不那么容易处理了。
要想直接解决⼀个规模较⼤的问题,有时是相当困难的。
分治法的设计思想是,将⼀个难以直接解决的⼤问题,分割成⼀些规模较⼩的相同问题,以便各个击破,分⽽治之。
分治策略是:对于⼀个规模为n的问题,若该问题可以容易地解决(⽐如说规模n较⼩)则直接解决,否则将其分解为k个规模较⼩的⼦问题,这些⼦问题互相独⽴且与原问题形式相同,递归地解这些⼦问题,然后将各⼦问题的解合并得到原问题的解。
这种算法设计策略叫做分治法。
第⼆步:分治法的理论基础如果原问题可分割成k个⼦问题,1<k≤n ,且这些⼦问题都可解并可利⽤这些⼦问题的解求出原问题的解,那么这种分治法就是可⾏的。
由分治法产⽣的⼦问题往往是原问题的较⼩模式,这就为使⽤递归技术提供了⽅便。
在这种情况下,反复应⽤分治⼿段,可以使⼦问题与原问题类型⼀致⽽其规模却不断缩⼩,最终使⼦问题缩⼩到很容易直接求出其解。
这⾃然导致递归过程的产⽣。
分治与递归像⼀对孪⽣兄弟,经常同时应⽤在算法设计之中,并由此产⽣许多⾼效算法。
2.1分治法所能解决的问题⼀般具有以下⼏个特征: 1) 该问题的规模缩⼩到⼀定的程度就可以容易地解决 2) 该问题可以分解为若⼲个规模较⼩的相同问题,即该问题具有最优⼦结构性质。
分治法解决循环赛日程表的递归方程)

分治法解决循环赛日程表的递归方程)分治法是一种解决问题的算法思想,它将一个大问题划分为若干个小问题,并分别解决这些小问题,最后将小问题的解合并得到原问题的解。
这种思想在循环赛日程表的递归方程中也可以得到应用。
循环赛日程表是指参赛团队之间进行循环对战的赛程安排表。
在一个参赛团队数量为n的循环赛中,每个团队需要与其他n-1个团队进行比赛,总共进行了(n-1) * n / 2场比赛。
解决循环赛日程表的递归方程可以分为三个步骤:1. 将参赛团队分为两个子集,分别是左侧子集和右侧子集。
如果参赛团队数量为奇数,可以将最后一个团队放入左侧子集。
2. 分别为左侧子集和右侧子集构造循环赛日程表。
这可以通过递归调用解决循环赛日程表的递归方程来实现。
递归的终止条件是子集中只有一个团队,此时不需要进行比赛。
3. 将左侧子集和右侧子集的日程表合并得到整个循环赛日程表。
合并的过程是将左侧子集的日程表和右侧子集的日程表进行对应位置的合并,合并后的结果即为整个循环赛日程表。
通过以上三个步骤,我们可以递归地构造出循环赛日程表。
这种分治法的思想能够将原问题划分为多个小问题来解决,从而提高问题的解决效率。
在实际应用中,分治法可以有效地解决循环赛日程表的问题。
通过将问题划分为若干个小问题,并逐步解决这些小问题,最后再将小问题的解合并得到原问题的解,可以高效地构造出循环赛日程表。
分治法是一种解决问题的有效算法思想,它可以应用于循环赛日程表的递归方程。
通过将问题划分为若干个小问题,并逐步解决这些小问题,最后将小问题的解合并得到原问题的解,可以高效地构造出循环赛日程表。
这种算法思想能够提高问题的解决效率,是解决循环赛日程表问题的一种有效方法。
使用分治策略递归和非递归和递推算法解决循环赛日程表课程设计报告

《算法设计与分析》课程设计报告题目:循环赛日程表院(系):信息科学与工程学院专业班级:软工学生姓名:学号:指导教师:2018 年 1 月 8 日至 2018 年 1 月 19 日算法设计与分析课程设计任务书目录1 常用算法 (1)1.1分治算法 (1)基本概念: (1)1.2递推算法 (2)2 问题分析及算法设计 (5)2.1分治策略递归算法的设计 (5)2.2 分治策略非递归算法的设计 (7)2.3 递推策略算法的设计 (8)3 算法实现 (9)3.1分治策略递归算法的实现 (9)3.2 分治策略非递归算法的实现 (10)3.3 递推策略算法的实现 (12)4 测试和分析 (15)4.1分治策略递归算法测试 (15)4.2分治策略递归算法时间复杂度的分析 (16)4.3 分治策略非递归算法测试 (16)4.4分治策略非递归算法时间复杂度的分析 (17)时间复杂度为:O(5^(n-1)) (17)4.5 递推策略算法测试 (17)4.6 递推策略算法时间复杂度的分析 (18)时间复杂度为:O(5^(n-1)) (18)4.7 三种算法的比较 (18)5 总结 (19)参考文献 (20)1 常用算法1.1分治算法基本概念:在计算机科学中,分治法是一种很重要的算法。
字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。
这个技巧是很多高效算法的基础,如排序算法(快速排序,归并排序),傅立叶变换(快速傅立叶变换)……任何一个可以用计算机求解的问题所需的计算时间都与其规模有关。
问题的规模越小,越容易直接求解,解题所需的计算时间也越少。
例如,对于n个元素的排序问题,当n=1时,不需任何计算。
n=2时,只要作一次比较即可排好序。
n=3时只要作3次比较即可,…。
而当n较大时,问题就不那么容易处理了。
循环赛日程表分治算法(c语言)

/**设有n=2k个运动员要进行网球循环赛。
现要设计一个满足以下要求的比赛日程表:*每个选手必须与其他n-1个选手各赛一次;*每个选手一天只能参赛一次;*xx在n-1天内结束。
*数组a[i][j]第i个选手在第j天所遇到的选手。
*/#include<stdio.h>#include<math.h>void gametable(int k){int a[100][100];int n,temp,i,j,p,t;n=2;//k=0两个参赛选手日程可以直接求得a[1][1]=1;a[1][2]=2;a[2][1]=2;a[2][2]=1;for(t=1;t<k;t++)//迭代处理,依次处理2^n....2^k个选手的比赛日程{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];}printf("参赛人数为:%d\n(第i行第j列表示和第i个选手在第j天比赛的选手序号)\n",n);for(i=1;i<=n;i++)for(j=1;j<=n;j++){printf("%d ",a[i][j]);if(j==n)printf("\n");}}void main(){int k;printf("比赛选手个数为n(n=2^k),请输入参数K(K>0):\n");scanf("%d",&k);if(k!=0)gametable(k);}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
/*
* 设有n=2k个运动员要进行网球循环赛。
现要设计一个满足以下要求的比赛日程表:
* 每个选手必须与其他n-1个选手各赛一次;
* 每个选手一天只能参赛一次;
* 循环赛在n-1天内结束。
* 数组a[i][j]第i个选手在第j天所遇到的选手。
*/
#include<stdio.h>
#include<math.h>
void gametable(int k)
{
int a[100][100];
int n,temp,i,j,p,t;
n=2;//k=0两个参赛选手日程可以直接求得
a[1][1]=1;a[1][2]=2;
a[2][1]=2;a[2][2]=1;
for(t=1;t<k;t++)//迭代处理,依次处理2^n....2^k个选手的比赛日程
{
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];
}
printf("参赛人数为:%d\n(第i行第j列表示和第i个选手在第j天比赛的选手序号)\n",n);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
printf("%d ",a[i][j]);
if(j==n)
printf("\n");
}
}
void main()
{
int k;
printf("比赛选手个数为n(n=2^k),请输入参数K(K>0):\n");
scanf("%d",&k);
if(k!=0)
gametable(k);
}。