【例】金块问题:老板有一袋金块(共n块),最优秀的雇员得到其中最重的一块,最差的雇员得到其中最轻的一块。假设有一台比较重量的仪器,我们希望用最少的比较次数找出最重和最轻的金块
解法一:将问题分为找到最大和最小两个子问题,对数据各进行一次遍历,找到最大和最小值
#include<iostream>
using namespace std;
int max=0,min=9999;
int main(){
int w[105];
int n;
cin>>n;
for(int i=0;i<n;i++)
cin>>w[i];
for(int i=0;i<n;i++){
if(a[i]>max){
max=a[i];
}
if(a[i]<min){
min=a[i];
}
}
cout<<max<<min<<endl;
return 0;
}
这种算法时间和空间复杂度均为O(n);
解法二 :将问题进一步分解,当n=1时,max=min=w[0]; 当n=2时,max=max(w[0],w[1]),min=min(w[0],w[1]),只需要进行一次比较。则当n=时,将数组分为两部分,前半部分的最大值为max1,最小值为min1,后半部分的最大值为max2,最小值为min2,则整体max=max(max1,max2),min=min(min1,min2)
#include<iostream>
using namespace std;
void Maxmin(int w[], int l, int r, int* max, int* min) {
if (l == r) {
*max = w[l];
*min = w[l];
return;
}
if (l + 1 == r) {
if (w[l] > w[r]) {
*max = w[l];
*min = w[r];
}
else {
*max = w[r];
*min = w[l];
}
return;
}
int mid = (l + r) / 2;
int lmax, lmin, rmax, rmin;
Maxmin(w, l, mid, &lmax, &lmin);
Maxmin(w, mid+1, r, &rmax, &rmin);
*max = lmax > rmax ? lmax : rmax;
*min = lmin < rmin ? lmin : rmin;
}
int main() {
int w[105];
int l=0, r;
int max,min;
cin >> r;
for (int i = 0; i < r; i++)
cin >> w[i];
Maxmin(w, l, r - 1, &max, &min);
cout << "最大值为:" << max << endl;
cout << "最小值为:" << min << endl;
return 0;
}
【例】循环赛日程安排问题
设有n=2
k
个运动员,要进行网球循环赛。现在要设计一个满足以下要求的比赛日程表:
① 每个选手必须与其他n-1个选手各赛一场
② 每个选手一天只能赛一次
③ 循环赛一共进行n-1天
根据分治法的思想,当n=2时,比赛进行1天,运动员A与运动员B进行比赛,当n=2k时,将队员分为两组,同一组的队员之间分别进行比赛。
#include<iostream>
using namespace std;
# define N 64
void matchTable(int** a, int n, int x, int y) {
if (n == 1)
return;
n /= 2; //将运动员分为两组
matchTable(a, n, x, y); //组内运动员比赛
matchTable(a, n, x, y + n);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
//组间运动员比赛
a[n + i][y + j]=a[i][n+y+j];
a[n + i][n + y + j] = a[i][y + j];
}
}
}
void tableShow(int** a, int n) {
// 输出循环日程表
for (int i = 0; i < n; i++) {
for (int j = 1; j <= n; j++)
printf("%d ", a[i][j]);
printf("\n");
}
}
void main() {
int n = 8;
int** a;
a = new int* [N];
for (int i = 0; i < N; i++) { a[i] = new int[N]; }
for (int i = 1; i <= n; i++) { a[0][i] = i; } //初始化第0天的比赛
matchTable(a, n, 0, 1);
tableShow(a, n);
//清理日程表矩阵a
for (int i = 0; i < N; i++) { delete[] a[i]; }
delete[] a;
}
代码执行结果:
每一行代表运动员的比赛日程,当运动员数量为2k-1时,可以假设有一个0号运动员,与0号运动员比赛即表示没有赛程。