題目:設有n=2^k個運動員要進行網球循環賽要設計一個滿足以下要求的比賽日程表:
- 每個選手必須與其他n-1個選手各賽一次;
- 每個選手每天只能賽一次;
- 循環賽一共進行n-1天。
按此要求可將比賽日程表設計成有n行和n-1列的表。在表中第i行和第j列處填入第i個選手在第j天所遇到的選手。
按照分治策略,可以將所有的選手分為兩半,n個選手的比賽日程表就可以通過為n/2個選手設計的比賽日程來決定。遞歸地用這種一分為二的策略對選手進行分割,直到只剩下2個選手時,比賽日程表的制定就變得很簡單。這時只要讓兩個選手進行比賽就可以了。
下圖列出的正方形表是8個選手的比賽日程表。其中左上角與左下角的2個小塊分別是選手1到選手4以及選手5到選手8前三天的比賽日程。據此,將左下角小塊中的所有數字按其對應位置抄到右上角,這樣就分別安排好了選手1到選手4以及選手5到選手8在后四天的比賽日程。以此思想很容易將這個比賽日程表推廣到具有任意多個選手的情景。

在一般情況下,算法可描述如下
1 #include <iostream> 2 #include <math.h> 3 using namespace std; 4 5 void Table(int k,int n,int **a); 6 void input(int &k); 7 void output(int **a,int n); 8 9 int main() 10 { 11 int k; 12 input(k); 13 14 int n=1; 15 //n=2k(k>=1)個選手參加比賽 16 for(int i=1; i<=k; i++) 17 n *= 2; 18 19 //根據n動態分配二維數組a 20 int **a = new int *[n+1]; 21 for(i=0;i<=n;i++) 22 { 23 a[i] = new int[n+1]; 24 } 25 26 27 Table(k,n,a); 28 29 cout<<"循環賽事日程表為:"<<endl; 30 output(a,n); 31 32 //釋放空間 33 for(i=0;i<=n;i++) 34 { 35 delete[] a[i]; 36 } 37 delete[] a; 38 39 return 0; 40 } 41 42 void input(int &k) 43 { 44 cout<<"請輸入k值:"<<endl; 45 cin>>k; 46 } 47 48 void output(int **a,int n) 49 { 50 for(int i=1; i<=n; i++) 51 { 52 for(int j=1; j<=n; j++) 53 { 54 cout<<a[i][j]<<" "; 55 } 56 cout<<endl; 57 } 58 } 59 60 void Table(int k,int n,int **a) 61 { 62 for(int i=1; i<=n; i++) 63 a[1][i]=i;//設置日程表第一行 64 65 int m = 1;//每次填充時,起始填充位置 66 for(int s=1; s<=k; s++) 67 { 68 n /= 2;//分割表格 69 for(int t=1; t<=n; t++) 70 { 71 for(int i=m+1; i<=2*m; i++)//控制行 72 { 73 for(int j=m+1; j<=2*m; j++)//控制列 74 { 75 a[i][j+(t-1)*m*2] = a[i-m][j+(t-1)*m*2-m];//右下角等於左上角的值 76 a[i][j+(t-1)*m*2-m] = a[i-m][j+(t-1)*m*2];//左下角等於右上角的值 77 } 78 79 } 80 } 81 m *= 2; 82 } 83 }