《算法问题实战策略》-chaper7-穷举法
关于这一章节《算法实战策略》有一段概述问题,我认为对于编程人员来说非常有价值,故在这里进行如下的摘抄:
构想算法是很艰难的工作。相比大家都经历过,面对复杂的要求只是傻乎乎地盯着显示器,或者不经过深思熟虑就开始打键盘,结果还要辛辛苦苦修改变得一塌糊涂的代码。经过这些磨难,各位就能切身体会到设计算法的重要性。
与通常所想不同,支配设计算法的并不是一时的灵感,而是许多策略性的选择。构想算法不仅需要理解问题的特性,还要理解执行时间和占用内存空间之间的对立关系,而且要会选择适当的数据结构。
算法设计范式指的是,算法为解决给定问题而采用的策略或观点。有些算法会共享出解决问题时最重要的领会,将之积累起来就会领悟到一种模式。从这个意义上说,这些领会是通过相同策略或相同范式解决问题的。
算法设计范式可作为设计算法的框架,因此,学习这些范式将有助于提高算法设计的能力。
——摘自《算法实战策略》
关于穷举法,可以说是计算机领域最为人熟知但却有大大忽略的一种基础算法了。很多人都会知道,它的思想就是将解空间给一一列举出来然后进行计数或者其他的什么操作。有较好算法基础的人会知道,搜索(DFS、BFS)本质上也是一种穷举,只不过他们针对不同类型的问题所设计出来的基于递归和搜索树结构的穷举方法,这里其实已经开始体现出穷举法解决问题的灵活性,并非很多人印象中那么简单。而利用穷举策略解决问题的时候,还将会面临下面几个大问题:
(1) 穷举过程中重复情况的计算:即我们要设计的穷举过程一定要“有序”,所谓“有序”就是要做到“不重不漏”的一一列举出所有情况。
(2) 穷举过程复杂度的分析:在具体的解题中我们往往会遇到穷举时时间、空间溢出的情况,这时候我们需要做的就是优化,映射到上文提及到的搜索其实就是剪枝策略。
那么下面我们结合这两个方面,通过具体的问题来实战体会这种范式设计思维。
Q:给出学生数n(n≤10)和他们之间的朋友关系,现在进行两两配对,请问有多少种不同的配对方法?
分析:
首先我们思考这道问题会有哪些重复计数的坑,能够看到,我们进行一组配对,比如(1,2)所形成的二元对视无序的,即(1,2)和(2,1)是一样的,对此我们在编程设计中,进行“配对”的时候就不能够设计两层循环了,而是通过规定二元对(a,b)中b>a来排除这些重复情况。
其次是对穷举过程复杂度的分析,基于个问题数据n的最大值,我们能够看到至多穷举的情况数是9*7*5*3*1 = 945,计算机处理起来是绰绰有余的因此不需要考虑优化。
另外要说的一个层面的问题是,在设计穷举的时候,如果说一种情况要分成多个决策过程,那么此时最好的方法就是基于递归和搜索树的深搜策略,它更加强调各种情况生成时的联系,而如果各种情况相对独立的话,那么进行简单的暴力枚举即可。
这道题目的函数代码如下:
 int n;
bool areFriend[][];
int countPairings(bool taken[])//标记配对情况的数组
{
    int  firstFree = -;
    for(int i = ;i < n;i++)//找到当前bool表中第一个没有配对的人
    {
          if(!taken[i])
          {
               firstFree = i;
               break;
          }
    }
    if(firstFree == -)  return ;   //所有人已完成配对,得到一种配对方法,返回1
    int ret = ;
    for(int pairWith = first +;pairWith < n;++pairWith)
    {
         if(!taken[pairWith] && areFriend[firstFree][pairWith])
         {
            taken[firstFree] = true;
            taken[pairWith]  = true;
            ret += countPairings(taken);
            taken[firstFree] = false;
            taken[pairWith]  = false;   
         }
    }
    return ret;
}
//由于数据较小,为了处理的方便,对于n<10的情况,我们可以将缺少的人记为已经配对,而在areFriend[][]需要初始化为0;而这一步骤在上面的部分代码中并没有体现,
//读者在完成完成代码的时候需要注意补充。
《算法问题实战策略》-chaper7-穷举法的更多相关文章
- 基本算法思想之穷举法(C++语言描述)
		
穷举算法(Exhaustive Attack method)是最简单的一种算法,其依赖于计算机的强大计算能力来穷尽每一种可能性,从而达到求解问题的目的.穷举算法效率不高,但是适应于一些没有规律可循的场 ...
 - 通过穷举法快速破解excel或word加密文档最高15位密码
		
1.打开文件 2.工具 --- 宏 ---- 录制新宏 --- 输入名字如 :aa 3.停止录制 ( 这样得到一个空宏 ) 4.工具 --- 宏 ---- 宏 , 选 aa, 点编辑按钮 5.删除窗口 ...
 - for循环语句以及迭代法和穷举法
		
循环语句: 四要素:初始条件,循环条件,状态改变,循环体 for(初始条件;循环条件;状态改变){ //循环体} 案例1:打印等腰直角三角形和菱形 左上三角 static void Main(stri ...
 - C#4 for循环  迭代法  穷举法应用
		
for()循环. 四要素: 初始条件,循环条件,状态改变,循环体. 执行过程: 初始条件--循环条件--循环体--状态改变--循环条件.... 注意:for的小括号里面分号隔开,for的小括号后不要加 ...
 - C# for 循环 迭代法   穷举法
		
for()循环. 四要素: 初始条件,循环条件,状态改变,循环体. 执行过程: 初始条件--循环条件--循环体--状态改变--循环条件.... 注意:for的小括号里面分号隔开,for的小括号后不要加 ...
 - 【2-24】for循环嵌套,跳转语句,异常语句,穷举法、迭代法
		
For循环嵌套与if嵌套相似,是在for中再套for,其结构如下: For(;;) { For(;;){} }经典题型为打印星星例: Console.Write("请输入一个奇数:" ...
 - 穷举法、for循环、函数、作用域、斐波那契数
		
1.穷举法 枚举所有可能性,直到得到正确的答案或者尝试完所有值. 穷举法经常是解决问题的最实用的方法,它实现起来热别容易,并且易于理解. 2.for循环 for语句一般形式如下: for variab ...
 - C#  异常语句  跳转语句  while循环  穷举法   迭代法
		
一 异常语句 ♦ try.....catch....finally 结构形式 try{ 可能会出错的代码语句 如果这里出错了,那么不会在继续下面的代码,而是直接进入catch中处理异常}catc ...
 - python 穷举法 算24点(史上最简短代码)
		
本来想用回溯法实现 算24点.题目都拟好了,就是<python 回溯法 子集树模板 系列 -- 7.24点>.无奈想了一天,没有头绪.只好改用暴力穷举法. 思路说明 根据四个数,三个运算符 ...
 
随机推荐
- UI实时预览最佳实践(转)
			
UI实时预览最佳实践 概要:Android中实时预览UI和编写UI的各种技巧.本文的例子都可以在结尾处的示例代码中看到并下载.如果喜欢请star,如果觉得有纰漏请提交issue,如果你有更好的点子可以 ...
 - Day2 - Python基础2 列表、字典、集合
			
Python之路,Day2 - Python基础2 本节内容 列表.元组操作 字符串操作 字典操作 集合操作 文件操作 字符编码与转码 1. 列表.元组操作 列表是我们最以后最常用的数据类型之一, ...
 - C#学习第四天
			
今天主要学习了结构方面的知识,首先是定义,代码: struct<typeName> { <memberDeclarations> } struct route { public ...
 - My.Ioc 代码示例——注册项的注销和更新
			
当您需要从 Ioc 容器中注销/删除一个注册项的时候,您会怎么做呢? 有人曾经在 stackoverflow 上提问“如何从 Unity 中注销一个注册项”.对于这个问题,有人的回答是“有趣.你为什么 ...
 - webconfig的设置节点几个说明
			
有助于深入理解webconfig <?xml version="1.0" encoding="utf-8" ?> <configuration ...
 - 计时器(Chronometer)的使用
			
安卓提供了一个计时器组件:Chronometer,该组件extends TextView,因此都会显示一段文本,但是它显示的时间是从某个起始时间开始过去了多少时间,它只提供了android:forma ...
 - PHP PDO获取结果集
			
一.介绍PDO获取结果集,不得不介绍一下PDO是如果执行SQL语句,一般情况下分三种, 1.query()方法 query()方法通常用于返回执行查询后的结果集.语法是这样的:PDOStatement ...
 - [转载]Java synchronized详解
			
在编写一个类时,如果该类中的代码可能运行于多线程环境下,那么就要考虑同步的问题.在Java中内置了语言级的同步原语--synchronized,这也大大简化了Java中多线程同步的使用.我们首先编写一 ...
 - 基于GBT28181:SIP协议组件开发-----------第四篇SIP注册流程eXosip2实现(一)
			
原创文章,引用请保证原文完整性,尊重作者劳动,原文地址http://www.cnblogs.com/qq1269122125/p/3945294.html. 上章节讲解了利用自主开发的组件SIP组件l ...
 - set_time_limit() 控制页面运行时间
			
当你的页面有大量数据时,建议使用set_time_limit()来控制运行时间,默认是30s,所以需要你将执行时间加长点,如 set_time_limit(300) ,其中将秒数设为0 ,表示持续运 ...