分治算法
-
将一个计算复杂的问题分为若干个子问题来进行求解,然后综合各个小问题得到复杂问题的最终答案
-
分解:
将原问题分解为若干规模较小的,相互独立,与原问题相同的子问题 -
解决:
如果小问题容易解决就解决若干的子问题,不然就是继续解决第一个步骤,直到子问题可以解决 -
合并:
将解决好的子问题的解合并为原问题的解有些问题是不需要合并子问题的解的,此时就不需要第三步了。
-
例题
-
乒乓球比赛日程问题:
问题:设有n名选手参赛,初赛进行n-1天,每位选手每一天必须比赛一次不轮空。- 分析:
- 对于n位选手来说,这是一个复杂的计算,可以将它分解为较为小的子问题,比如说只有两个人参赛;
- 解决两个人参赛的赛程,发现还是不足以分配,然后再分析4个人、8个人……等,直到问题得以解决
- 分析:
-
解决:
#include<stdio.h>
#include<stdlib.h>
void schedule(int n,int m);
int check(int m);
int player[65][65] = {0};
int main()
{
int m;
printf("输入参赛人数:");
scanf("%d",&m);
if(!check(m)){
printf("输入的数必须是2的整数幂");
return 0;
}
schedule(1,m);
for(int i = 1;i <= m;i++){
for(int j = 1;j <= m;j++){
printf("%3d",player[i][j]);
}
printf("\n");
}
}
void schedule(int n,int m)
{
if(m == 2){ //达到最小可以解决的时候
player[n][1] = n;
player[n][2] = n+1;
player[n+1][1] = n+1;
player[n+1][2] = n;
}else{
schedule(n,m/2);//没到最小可以解决的时候就继续分解
schedule(n + m/2,m/2);//这时候已经解决完了最小可解决问题,回来解决另一半的最小程度m
//开始解决剩下的部分
for(int i = n+m/2;i <= n+m; i++){
for(int j = m/2 + 1;j <= m;j++){
player[i][j] = player[i - m/2][j - m/2];
}
}
for (int i = n; i < n + m/2; i++){
for(int j = m/2 + 1;j <= m; j++){
player[i][j] = player[i + m/2][j - m/2];
}
}
}
}
int check(int m)
{
int i = 2;
int j = 2;
for(int i;i < 8;i++){
j *= 2;
if(j == m) break;
}
if(i >= 8){
return 0;
}
return 1;
}