博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
算法洗脑系列(8篇)——第五篇 分治思想
阅读量:6417 次
发布时间:2019-06-23

本文共 4157 字,大约阅读时间需要 13 分钟。

    由于最近工作比较忙,好长时间都没有更新博客了,今天就分享下分治思想。

 

一: 思想

     有时候我们处理一个复杂的问题,可能此问题求解步骤非常杂,也可能是数据非常多,导致我们当时很难求出或者无法求出,古语有云:

步步为营,各个击破,这个思想在算法中称为分治思想,就是我们可以将该问题分解成若干个子问题,然后我们逐一解决子问题,最后将子问题

的答案组合成整个问题的答案。

 

二: 条件

     当然各个思想都有它的使用领域,所以玩这场分治游戏就要遵守它的游戏规则。

       ①   求解问题确实能够分解成若干个规模较小的子问题,并且这些子问题最后能够实现接近或者是O(1)时间求解。

       ②   各个子问题之间不能有依赖关系,并且这些子问题确实能够通过组合得到整个问题的解。

 

三:步骤

     通过上面对分治的说明,可以看到分治分三步走:

       ①  分解: 将问题分解成若干了小问题。

       ②  求解: O(1)的时间解决该子问题。

       ③  合并: 子问题逐一合并构成整个问题的解。

 

四:举例

      有n位选手参加羽毛球赛,比赛要进行n-1天,每位选手都要与其他每一个选手比赛一场并且每位选手每天都要比赛一场,请根据比赛要求

   排出选手的比赛日程表。

 

   思路:首先我们拿到问题要给自己打气,哈哈,因为日常的基本问题都跑不出我们所知道算法思想的范畴,此问题也包括在内。

           当n是8,16,32时,面对这么一个庞大的问题我们可能就崩溃了,因为我们实在无法求出来,此时我们就要想想是否可以分治一下。

           ①  就拿16个选手的比赛安排来说,需要比赛15天。

           ②  分成2个8位选手7天的比赛安排。

           ③  分为4个4位选手3天的比赛安排。

           ④  分为8个2位选手1天的比赛安排。

         相信2位选手1天的比赛安排大家都会吧,如图:

        然后退化到第三步即4位选手3天的比赛安排,如图:

        在图中可以看出:

          第一天:将1,2位和3,4位选手的日程合并。

          第二天,第三天:这两天的比赛安排其实可以发现规律的,整个表格可以划分四格,对角赋值。

  

程序代码如下:

1 using System;   2 using System.Collections.Generic;   3 using System.Linq;   4 using System.Text;   5   6 namespace Fenzhi   7 {
8 public class Program 9 {
10 //这里 11 static int[,] GameList = new int[8, 8]; 12 13 static void Main(string[] args) 14 {
15 Console.Write("请输入参赛选手的人数:\t"); 16 17 int person = Convert.ToInt32(Console.ReadLine()); 18 19 //参数检查合法性 20 if (person % 2 != 0) 21 {
22 Console.WriteLine("输入的人数必须是2的倍数!"); 23 return; 24 } 25 26 //因为我定了只能容纳8位选手的日程的比赛安排,多的话就会爆掉 27 if (person > 8) 28 {
29 Console.WriteLine("对不起,最多8位选手"); 30 return; 31 } 32 33 //调用分值计算函数 34 GameCal(1, person); 35 36 Console.Write("\n编号\t"); 37 38 //最后就是将数组表头 39 for (int i = 1; i < person; i++) 40 {
41 Console.Write("第{0}天\t", i); 42 } 43 44 //换行 45 Console.WriteLine(); 46 47 //输出数组内容 48 for (int i = 0; i < person; i++) 49 {
50 for (int j = 0; j < person; j++) 51 {
52 Console.Write("{0}\t", GameList[i, j]); 53 } 54 Console.WriteLine(); 55 } 56 57 Console.ReadLine(); 58 } 59 60 /// 61 /// 分治计算 62 /// 63 /// 起始选手编号 64 /// 选手的人数(因为是分治,所以每次砍半) 65 static void GameCal(int index, int num) 66 {
67 //如果人数为2,则说明已经分治到了最简问题 68 if (num == 2) 69 {
70 //参赛选手编号 71 GameList[index - 1, 0] = index; 72 73 //对阵选手编号 74 GameList[index - 1, 1] = index + 1; 75 76 //参赛选手编号 77 GameList[index, 0] = index + 1; 78 79 //对阵选手编号 80 GameList[index, 1] = index; 81 } 82 else 83 {
84 //折半递归 85 GameCal(index, num / 2); 86 87 //折半递归 88 GameCal(index + num / 2, num / 2); 89 90 /* 子问题都结束后就要想办法合并,根据发现的规律进行合并 */ 91 92 //用于将“左下角”填充到“右上角” 93 //控制横坐标 94 for (int i = index; i < index + num / 2; i++) 95 {
96 //控制“纵坐标” 97 for (int j = num / 2; j < num; j++) 98 {
99 //对角赋值 100 GameList[i - 1, j] = GameList[(i - 1) + num / 2, j - num / 2]; 101 } 102 } 103 104 //用于将“左上角”填充到“右下角” 105 //控制横坐标 106 for (int i = index + num / 2; i < index + num; i++) 107 {
108 //控制纵坐标 109 for (int j = num / 2; j < num; j++) 110 {
111 //对角赋值 112 GameList[i - 1, j] = GameList[(i - 1) - num / 2, j - num / 2]; 113 } 114 } 115 } 116 } 117 } 118 }

转载地址:http://fdpra.baihongyu.com/

你可能感兴趣的文章
mysql查询结果单位换算后保留两位小数
查看>>
[swift 进阶]读书笔记-第七章:字符串 C7P8 文本输出流
查看>>
4. 单例模式
查看>>
Activity与Fragment的生命周期
查看>>
HttpClient 4.3超时设置
查看>>
PHPCMS2008利用EXP
查看>>
活动的生存期
查看>>
为什么Linux不需要碎片整理?
查看>>
Windows Server 2012 R2 文件服务器安装与配置01 之目录说明
查看>>
最简单的Go环境搭建(Ubuntu)
查看>>
Nginx性能优化
查看>>
Hadoop中的ProxyUser
查看>>
win7实现远程关机-可以批量局域网远程关机
查看>>
Azure 安装.NET3.5机能错误一例
查看>>
Oracle 中ROWNUM用法总结,ROWNUM 与 ROWID 区别
查看>>
ios获取app版本号
查看>>
servlet通过过滤器处理字符集
查看>>
5月28日
查看>>
java策略模式
查看>>
Extjs gridPanl中本地数据分页
查看>>