算法之枚举思想

一: 思想

有时我们解决某个问题时找不到一点规律,此时我们很迷茫,很痛苦,很蛋疼,突然我们灵光一现,发现候选答案的问题规模在百万之内,

此时我们就想到了从候选答案中逐一比较,一直找到正确解为止。

二: 条件

前面也说了,枚举是我们在无奈之后的最后一击,那么使用枚举时我们应该尽量遵守下面的两个条件。

①   地球人都不能给我找出此问题的潜在规律。

②   候选答案的集合是一个计算机必须能够承受的。

三:举例

下面是一个填写数字的模板,其中每个字都代表数字中的”0~9“,那么要求我们输入的数字能够满足此模板。

思路:首先拿到这个题,蛋还是比较疼的,因为找不到好的解题思路,仔细想想这属于查找类型的问题,常用的查找也就5种,能适合

该问题的查找也就”顺序查找“和”二分查找“,然后仔细看看问题规模最多也就105=100000,其实根据“二分"的思想在这个问题

中并不合适,最后只能用“顺序查找“了。

 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5  6 namespace Meiju 7 { 8     class Program 9     {10         static void Main(string[] args)11         {12             int count = 0;13 14             //“算”字的取值范围15             for (int i1 = 1; i1 < 10; i1++)16             {17                 //“法”字的取值范围18                 for (int i2 = 0; i2 < 10; i2++)19                 {20                     //“洗”字的取值范围21                     for (int i3 = 0; i3 < 10; i3++)22                     {23                         //"脑"字的取值范围24                         for (int i4 = 0; i4 < 10; i4++)25                         {26                             //"题"字的取值范围27                             for (int i5 = 1; i5 < 10; i5++)28                             {29                                 count++;30 31                                 //一个猜想值32                                 var guess = (i1 * 10000 + i2 * 1000 + i3 * 100 + i4 * 10 + i5) * i1;33 34                                 //最终结果值35                                 var result = i5 * 100000 + i5 * 10000 + i5 * 1000 + i5 * 100 + i5 * 10 + i5;36 37                                 if (guess == result)38                                 {39                                     Console.WriteLine("\n\n不简单啊,费了我  {0}次,才tmd的找出来\n\n", count);40 41                                     Console.WriteLine("\t{0}\t{1}\t{2}\t{3}\t{4}", i1, i2, i3, i4, i5);42                                     Console.WriteLine("\n\n\tX\t\t\t\t{0}", i1);43                                     Console.WriteLine("—————————————————————————————");44                                     Console.WriteLine("\n{0}\t{1}\t{2}\t{3}\t{4}\t{5}", i5, i5, i5, i5, i5, i5);45 46                                     Console.Read();47                                 }48 49                                 Console.WriteLine("第{0}搜索", count);50 51                             }52                         }53                     }54                 }55             }56 57             Console.Read();58         }59     }60 }

最后我们还是解决了问题,发现其中的时间复杂度达到了O(n5),这个复杂度理论上是让人不能接收的,还好我们的n在10以内,

n的每一次的自增对cpu来说都是莫大的伤害。

有一种简单的算法就是从积枚举,因为积的形态比较特殊,xxxxx,所以只有9种11111、22222、33333、44444、55555、66666、77777、88888、99999.这样算法的复杂度瞬间就降到了n2。

现将你的想法用code实现一下。

 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5  6 namespace ConsoleApplication1 7 { 8     class Program 9     {10         static void Main(string[] args)11         {12             //商13             int[] resultArr = { 111111, 222222, 333333, 444444, 555555, 666666, 777777, 888888, 999999 };14 15             //除数16             int[] numArr = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };17 18             int count = 0;19 20             for (int i = 0; i < resultArr.Count(); i++)21             {22                 for (int j = 0; j < numArr.Count(); j++)23                 {24                     count++;25 26                     var result = resultArr[i].ToString();27 28                     var num = numArr[j].ToString();29 30                     var origin = (resultArr[i] / numArr[j]).ToString();31 32                     if (origin.LastOrDefault() == result.FirstOrDefault()33                         && origin.FirstOrDefault() == num.FirstOrDefault()34                         && result.Length - 1 == origin.Length)35                     {36                         Console.WriteLine("\n\n费了{0} 次,tmd找出来了", count);37                         Console.WriteLine("\n\n感谢一楼同学的回答。现在的时间复杂度已经降低到O(n2),相比之前方案已经是秒杀级别\n");38 39                         Console.WriteLine("\t{0}\t{1}\t{2}\t{3}\t{4}", origin.ElementAt(0), origin.ElementAt(1), origin.ElementAt(2), origin.ElementAt(3), origin.ElementAt(4));40                         Console.WriteLine("\n\n\tX\t\t\t\t{0}", num);41                         Console.WriteLine("—————————————————————————————");42                         Console.WriteLine("\n{0}\t{1}\t{2}\t{3}\t{4}\t{5}", result.ElementAt(0), result.ElementAt(0), result.ElementAt(0), result.ElementAt(0), result.ElementAt(0), result.ElementAt(0));43 44                         Console.Read();45                     }46                     Console.WriteLine("第{0}搜索", count);47                 }48             }49             Console.WriteLine("无解");50             Console.Read();51         }52     }53 }

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-05 17:07:13

算法之枚举思想的相关文章

排序算法的基本思想和OC代码实现

算法的基本思想和OC代码实现 一 .冒泡排序   (平均时间复杂度 o(N*N))  基本思想:两个数比较大小,较大的数下沉,较小的数冒起来. 过程:比较相邻的两个数据,如果第二个数小,就交换位置 从后向前两两比较,一直到比较最前两个数据.最终最小数被交换到起始的位置,这样第一个最小数的位置就排好了. 继续重复上述过程,依次将第2,3,….,n-1个最小数排好位置. int arr[5]={23,21,45,23,64}; int temp; for (int i=0; i<4; i++) {

经典算法宝典——动态规划思想(六)(2)

1.01背包问题 有N件物品和一个容量为V的背包,第i件物品的体积是c[i],价值是w[i].求解将哪些物品装入背包可使价值总和最大. 解析: 这是最基础的背包问题,特点是每种物品仅有一件,可以选择放或不放.用子问题定义状态,即f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值.其状态转移方程便是f[i][v] = max{f[i-1][v], f[i-1][v-c[i]]+w[i]},这个方程非常重要,基本上所有跟背包相关的问题的方程都是由它衍生出来的,所以有必要将它详细解

经典算法宝典——贪婪思想(五)(1)

贪婪法(Greedy)又叫登山法,它的根本思想是逐步到达山顶,即逐步获得最优解,是解决最优化问题时的一种简单但适用范围有限的策略."贪婪"可以理解为以逐步的局部最优,达到最终的全局最优. 贪婪算法没有固定的算法框架,算法设计的关键是贪婪策略的选择.一定要注意,选择的贪婪策略要具有无后向性,即某阶段状态一旦确定以后,不受这个状态以后的决策影响.也就是说某状态以后的过程不会影响以前的状态,只与当前状态有关,也称这种特性为无后效性.因此,适应用贪婪策略解决的问题类型较少,对所采用的贪婪策略一

经典算法宝典——分治思想(四)(1)

分治法(Divide and Conquer)的设计思想是,将一个难以直接解决的大问题,分割成一些规模较小的几个相似问题,以便各个击破,分而治之. 说明: 分治策略的应用很广,具体表现形式各异,比如:折半查找.合并排序.快速排序.二叉树遍历(先遍历左子树再遍历右子树).二叉排序树的查找等算法. 一.分治算法框架 1.算法设计思想 分治法求解问题的过程是,将整个问题分解成若干个小问题后分而治之.如果分解得到的子问题相对来说还太大,则可反复使用分治策略将这些子问题分成更小的同类型子问题,直至产生出方

javascript 利用 - 枚举思想 - 添加地名的一个小例子

利用枚举思想来添加地名,主要功能是:判断点击a标签(即当前的地名)如果在ul的li不存在的话那么就添加,有则不添加,而且还提供了相应的排序功能... HTML代码: <div id="china"> <a href="javascript:;">广州</a> <a href="javascript:;">深圳</a> <a href="javascript:;"

数据挖掘十大算法总结--核心思想,算法优缺点,应用领域

本文所涉算法均只概述核心思想,具体实现细节参看本博客"数据挖掘算法学习"分类下其他文章,不定期更新中.转载请注明出处,谢谢. 参考了许多资料加上个人理解,对十大算法进行如下分类: ?分类算法:C4.5,CART,Adaboost,NaiveBayes,KNN,SVM ?聚类算法:KMeans ?统计学习:EM ?关联分析:Apriori ?链接挖掘:PageRank 其中,EM算法虽可以用来聚类,但是由于EM算法进行迭代速度很慢,比kMeans性能差很多,并且KMeans算法 聚类效果

经典算法宝典——迭代思想(二)(1)

迭代法(Iteration)也称"辗转法",是一种不断用变量的旧值递推出新值的解决问题的方法. 说明: 迭代算法一般用于数值计算,比如累加.累乘都是迭代算法策略的基础应用. 利用迭代算法策略求解问题,设计工作主要有3步. (1)确定迭代模型 根据问题描述,分析得出前一个(或几个)值与其下一个值的迭代关系数学模型.当然这样的迭代关系,最终会迭代出求解的目标.确定迭代模型是解决迭代问题的关键. (2)建立迭代关系式 递推数学模型一般是带下标的字母,算法设计中要将其转化为"循环不变

八大排序算法实战:思想与实现

摘要: 所谓排序,就是根据排序码的递增或者递减顺序把数据元素依次排列起来,使一组任意排列的元素变为一组按其排序码线性有序的元素.本文将介绍八种最为经典常用的内部排序算法的基本思想与实现,包括插入排序(直接插入排序,希尔排序).选择排序(直接选择排序,堆排序).交换排序(冒泡排序,快速排序).归并排序.分配排序(基数排序),并给出各种算法的时间复杂度.空间复杂度和稳定性. 版权声明: 本文原创作者:书呆子Rico  作者博客地址:http://blog.csdn.net/justloveyou_/

1-6、算法设计常用思想之迭代法

人们提出了很多迭代法来近似求解这类问题,比较常见的有梯度法.最小二乘法和牛顿迭代法,只要问题的解是可收敛的(或者是局部可收敛的),都可以使用迭代法求解. 数学意义上的迭代法是一种不断用变量的旧值递推新值的过程,其对应的迭代算法也是用计算机解决问题的一种基本方法. 迭代法和递推法的关系迭代法作为很多数学问题的求解算法,是解决数学问题的一种常用的算法模式,可以独立构成解决问题的算法.递推法作为一种设计算法的常用思想,没有固定的算法实现模式,通常是与其他算法模式配合形成算法实现.比如线性动态规划问题,