一、算法要求
设计一个满足以下要求的比赛日程表:
(1) 每个选手必须与其他n-1个选手各赛一次;
(2) 每个选手一天只能赛一次;
(3) 循环赛一共进行n-1天。
传统方法:将比赛日程表设计为:n行 n-1列的表(i,j)表示:第i个选手在第j 天 遇到的选手。
1. 思路
分治法不仅可以用来设计算法,在其他方面也有广泛应用,如用分治思想来设计电路、构造数学证明等。
举例说明。
设有n=2个运动员要进行网球循环赛。现要设计一个满足以下要求的比赛日程表:
①每个选手必须与其他n-1个选手各赛一次;
②每个选手一天只能赛一次;
③循环赛一共进行n-1天。
按此要求可将比赛日程表设计成有n行和n-1列的表。在表中第i行和第j列处填入第i个选手在第j天所遇到的选手。
按分治策略,可以将所有选手对分为两半,n个选手的比赛日程表就可以通过为n/2个选手设计的比赛日程表来决定。
递归地用这种一分为二的策略对选手进行分割,直到只剩下两个选手时,比赛日程表的制定就变得简单了。
这时只要让这两个选手进行比赛就可以了。
2. 示例
二、完整代码
1. 主文件
main.cpp:
// Project1_2: 循环赛日程表
#include<iostream>
#include<iomanip>
using namespace std;
void Print(int** a, int n){
for (int i = 1; i <= n; i++){
for (int j = 1; j <= n; j++){
cout << "|" << setw(2) << a[i][j];
}
cout <<"|" << endl;
}
}
void Schedule(int k, int n, int** a)
{
for (int i = 1; i <= n; i++)
a[1][i] = i;//设置日程表第一行
int m = 1;//每次填充时,起始填充位置
for (int s = 1; s <= k; s++)
{
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) * 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];//左下角等于右上角的值
}
}
}
m *= 2;
}
}
int main() {
int k, // 参赛人数是2^k次方
n; // 参赛人数
cout << "#Please enter the number of people (index ‘k’ with base 2): ";
cin >> k;
n = pow(2, k);
int** a = new int* [n + 1];//动态分配二维数组a
for (int i = 0; i < n + 1; i++) {
a[i] = new int[n + 1];
}
Schedule(k, n, a);
cout << "\n#The recurring event schedule is:" << endl;
Print(a, n);
//释放空间
for (int i = 0; i < n + 1; i++) {
delete[] a[i];
}
delete[] a;
return 0;
}
2. 效果展示
输入:
参赛人数:2的指数k = 4;
输出:
三、补充
分治法是一种一般性的算法设计技术,它将问题的实例划分为若干个较小的实例(最好用有相同的规模),对这些小的问题求解,然后合并这些解,得到原是问题的解。
分治法的时间效率满足:T(n)=aT(n/b)+f(n)
分治法基本思想和基本步骤:
divide-and-conquer(P)
{
if ( | P | <= n0) adhoc(P); //解决小规模的问题
divide P into smaller subinstances P1,P2,...,Pk;//分解问题
for (i=1,i<=k,i++)
yi=divide-and-conquer(Pi); //递归的解各子问题
return merge(y1,...,yk); //将各子问题的解合并为原问题的解
}
在用分治法设计算法时,最好使子问题的规模大致相同。即将一个问题分成大小相等的k个子问题的处理方法是行之有效的。
这种使子问题规模大致相等的做法是出自一种平衡(balancing)子问题的思想,它几乎总是比子问题规模不等的做法要好。
文档供本人学习笔记使用,仅供参考。