分治法实现循环日程表。
什么是分治法?
分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同。求出子问题的解,就可得到原问题的解。
我的理解是将问题分而治之,大问题和小问题具有相同的解决方法,那么我们解决问题就可以从下而上。只需要写出最小子问题的代码,利用递归或循环等方法就能解决。
问题描述:
设有n=2^k个运动员要进行网球循环赛。现要设计一个满足以下要求的比赛日程表:
(1)每个选手必须与其他n-1个选手各赛一次;
(2)每个选手一天只能参赛一次;
(3)循环赛在n-1天内结束。
解决思想:
第一列代表队伍序号,后n-1列表示比赛对手。
当k=1时,n=2。
1 | 2 |
2 | 1 |
当k=2时,n=4。
1 | 2 | 3 | 4 |
2 | 1 | 4 | 3 |
3 | 4 | 1 | 2 |
4 | 3 | 2 | 1 |
来找找规律吧。
其实上表已经可以总结出规律,敲重点!!!分治法的思想是什么,分而治之。无论问题有多大,我们只需要理解子问题。
将它们划分为一小块,可以看见n=4时是由n=2演变而来的。为了满足题目要求,一人每天只能比一次比赛,所以我们将它们作为一个整体,将左上角的表格填充到右下角,将左下角的表格填充到右上角。
以此类推k=3,n=8时:
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<stdio.h>
int main(){
int k=3,i,j,n,temp,t;
int count=0;
n=2;
int a[9][9]={0};
a[1][1]=1;
a[2][1]=2;
a[1][2]=2;
a[2][2]=1;
for(t=1;t<k;t++){
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];
}
for(i=1;i<=1<<k;i++) //输出二维数组
for(j=1;j<=1<<k;j++){
printf("%4d",a[i][j]);
count++;
if(count%8==0) printf("\n");
}
return 0;
}