问题标题: 酷町堂:枚举2

0
1
已解决
李泽远
李泽远
高级天翼
高级天翼

试问枚举的意义?
 为什么非要用enum?

https://app.xuty.tk/static/app/index.html


 蒟蒻声明:
 本蒟蒻是在C++ primer plus上学的枚举,
 上面没讲太清楚,请各位大佬给我讲讲吧。


0
已采纳
周琪岳
周琪岳
资深光能
资深光能

enum是计算机编程语言中的一种数据类型。枚举类型:在实际问题中,有些变量的取值被限定在一个有限的范围内。例如,一个星期内只有七天,一年只有十二个月,一个班每周有六门课程等等。如果把这些量说明为整型,字符型或其它类型显然是不妥当的。为此,C语言提供了一种称为“枚举”的类型。在“枚举”类型的定义中列举出所有可能的取值,被说明为该“枚举”类型的变量取值不能超过定义的范围。应该说明的是,枚举类型是一种基本数据类型,而不是一种构造类型,因为它不能再分解为任何基本类型。

1
1
高子健
高子健
新手天翼
新手天翼

java enum(枚举)使用详解+ 总结

enum 的全称为 enumeration, 是 JDK 1.5 中引入的新特性,存放在 java.lang 包中。

下面是我在使用 enum 过程中的一些经验和总结。

原始的接口定义常量

语法(定义)

创建枚举类型要使用 enum 关键字,隐含了所创建的类型都是 java.lang.Enum 类的子类(java.lang.Enum 是一个抽象类)。枚举类型符合通用模式 Class Enum

这段代码实际上调用了7次 Enum(String name, int ordinal):

遍历、switch 等常用操作

对enum进行遍历和switch的操作示例代码:

输出结果:

enum 对象的常用方法介绍

 

int compareTo(E o) 

比较此枚举与指定对象的顺序。

 

Class getDeclaringClass() 

返回与此枚举常量的枚举类型相对应的 Class 对象。

 

String name() 

返回此枚举常量的名称,在其枚举声明中对其进行声明。

 

int ordinal() 

返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零)。

 

String toString() 

返回枚举常量的名称,它包含在声明中。

 

static

输出结果:

给 enum 自定义属性和方法

给 enum 对象加一下 value 的属性和 getValue() 的方法:

输出结果:

EnumSet,EnumMap 的应用

原理分析

 

enum 的语法结构尽管和 class 的语法不一样,但是经过编译器编译之后产生的是一个class文件。该class文件经过反编译可以看到实际上是生成了一个类,该类继承了java.lang.Enum。EnumTest 经过反编译(javap com.hmw.test.EnumTest 命令)之后得到的内容如下:

所以,实际上 enum 就是一个 class,只不过 java 编译器帮我们做了语法的解析和编译而已。

 

总结

 

可以把 enum 看成是一个普通的 class,它们都可以定义一些属性和方法,不同之处是:enum 不能使用 extends 关键字继承其他类,因为 enum 已经继承了 java.lang.Enum(java是单一继承)。

http://wenku.cyjzzd.com/a/1300001419##wk-more如果不懂

望采纳!!!

高子健在2019-09-19 19:27:00追加了内容

步骤1——枚举量的声明和定义方法/步骤1:

首先,请看下面的语句:

enum enumType {Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday};

这句话有两个作用:

第一:声明enumType为新的数据类型,称为枚举(enumeration);

第二:声明Monday、Tuesday等为符号常量,通常称之为枚举量,其值默认分别为0-6。(后面会介绍怎样显式的初始化枚举量的值)

方法/步骤2:

接着利用新的枚举类型enumType声明这种类型的变量:

enumType Weekday;

就像使用基本变量类型int声明变量一样,如 int a;

然而与基本变量类型不同的地方是,在不进行强制转换的前提下,只能将定义的枚举量赋值给该种枚举的变量,如:

Weekday = Monday;

或者

Weekday = Sunday;

不能将其他值赋给枚举变量,如:

Weekday = 10;

这是不允许的,因为10不是枚举量

也就是说Weekday只能是定义的Monday-Sunday这些定义过的枚举量

然而这不是绝对的,第六条会讲到利用强制类型转换将其他类型值赋给枚举变量

方法/步骤3:

上面讲不能将枚举量赋给枚举变量,那么能不能将枚举量赋给非枚举变量呢?如:

int a=Monday;

这是允许的,因为枚举量是符号常量,这里的赋值编译器会自动把枚举量转换为int类型。

方法/步骤4:

前面讲可以对枚举进行赋值运算,那枚举变量能不能进行算术运算呢?

Weekday++;

Weekday = Monday + Tuesday;

这是非法的,因为这些操作可能导致违反类型限制,比如:

Weekday = Sunday;

Weekday++;

Weekday首先被赋予枚举量中的最后一个值Sunday(值为6),再进行递增的话,Weekday增加到7,而对于enumType类型来说,7是无效的。

总结:对于枚举,只定义了赋值运算符,没有为枚举定义算术运算。

方法/步骤5:

不能对枚举量进行算术运算,那么枚举量能不能参与其他类型变量的运算呢?

int a;

a = 1 + Monday;

这是允许的,因为编译器会自动把枚举量转换为int类型。

方法/步骤6:

第二条讲:在不进行强制转换的前提下,只能将定义的枚举量赋值给该种枚举的变量,言下之意就是可以通过强制转换将其他类型值赋给枚举变量

Weekday = enumType(2);

等同于:

Weekday = Wednesday;

但是,如果试图将一个超出枚举取值范围的值通过强制转换赋给枚举变量,会出现什么结果?

Weekday = enumType(20);

结果将是不确定的,这么做不会出错,但得不到想要的结果。

步骤2——自定义枚举量的值方法/步骤1:

前面讲通过定义

enum enumType {Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday};

枚举量Monday、Tuesday等的值默认分别为0-6,我们可以显式的设置枚举量的值:

enum enumType {Monday=1, Tuesday=2, Wednesday=3, Thursday=4, Friday=5, Saturday=6, Sunday=7};

指定的值必须是整数

方法/步骤2:

也可以只显式的定义一部分枚举量的值:

enum enumType {Monday=1, Tuesday, Wednesday=1, Thursday, Friday, Saturday, Sunday};

这样Monday、Wednesday均被定义为1,则Tuesday=2,Thursday、Friday、Saturday、Sunday的值默认分别为2、3、4、5.

总结:未被初始化的枚举值的值默认将比其前面的枚举值大1。

方法/步骤3:

第二条还说明另外一个现象,就是枚举量的值可以相同。

步骤3——枚举的取值范围方法/步骤1:

前面讲到可以通过强制转换将其他类型值赋给枚举变量:

Weekday = enumType(2);

这是合法的;但是

Weekday = enumType(20);是非法的。

这里涉及枚举取值范围的概念:

枚举的上限是 大于最大枚举量的 最小的2的幂,减去1;

枚举的下限有两种情况:一、枚举量的最小值不小于0,则枚举下限取0;二、枚举量的最小值小于0,则枚举下限是 小于最小枚举量的 最大的2的幂,加上1。

举例来讲:

假如定义 enum enumType1 { First=-5,Second=14,Third=10 };

则枚举的上限是16-1=15(16大于最大枚举量14,且为2的幂);

枚举的下限是-8+1=-7(-8小于最小枚举量-5,且为2的幂);

步骤4——枚举应用方法/步骤1:

个人觉得枚举switch是最好的搭档:

enum enumType{Step0, Step1, Step2}Step=Step0;

//注意这里在声明枚举的时候直接定义了枚举变量Step,并初始化为Step0

switch (Step)

{

case Step0:{...;break;}

case Step1:{...;break;}

case Step2:{...;break;}

default:break;

}

注意事项

在实际应用中,枚举常常用来定义符号常量。

高子健在2019-09-19 19:27:24追加了内容

步骤1——枚举量的声明和定义方法/步骤1:

首先,请看下面的语句:

enum enumType {Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday};

这句话有两个作用:

第一:声明enumType为新的数据类型,称为枚举(enumeration);

第二:声明Monday、Tuesday等为符号常量,通常称之为枚举量,其值默认分别为0-6。(后面会介绍怎样显式的初始化枚举量的值)

方法/步骤2:

接着利用新的枚举类型enumType声明这种类型的变量:

enumType Weekday;

就像使用基本变量类型int声明变量一样,如 int a;

然而与基本变量类型不同的地方是,在不进行强制转换的前提下,只能将定义的枚举量赋值给该种枚举的变量,如:

Weekday = Monday;

或者

Weekday = Sunday;

不能将其他值赋给枚举变量,如:

Weekday = 10;

这是不允许的,因为10不是枚举量

也就是说Weekday只能是定义的Monday-Sunday这些定义过的枚举量

然而这不是绝对的,第六条会讲到利用强制类型转换将其他类型值赋给枚举变量

方法/步骤3:

上面讲不能将枚举量赋给枚举变量,那么能不能将枚举量赋给非枚举变量呢?如:

int a=Monday;

这是允许的,因为枚举量是符号常量,这里的赋值编译器会自动把枚举量转换为int类型。

方法/步骤4:

前面讲可以对枚举进行赋值运算,那枚举变量能不能进行算术运算呢?

Weekday++;

Weekday = Monday + Tuesday;

这是非法的,因为这些操作可能导致违反类型限制,比如:

Weekday = Sunday;

Weekday++;

Weekday首先被赋予枚举量中的最后一个值Sunday(值为6),再进行递增的话,Weekday增加到7,而对于enumType类型来说,7是无效的。

总结:对于枚举,只定义了赋值运算符,没有为枚举定义算术运算。

方法/步骤5:

不能对枚举量进行算术运算,那么枚举量能不能参与其他类型变量的运算呢?

int a;

a = 1 + Monday;

这是允许的,因为编译器会自动把枚举量转换为int类型。

方法/步骤6:

第二条讲:在不进行强制转换的前提下,只能将定义的枚举量赋值给该种枚举的变量,言下之意就是可以通过强制转换将其他类型值赋给枚举变量

Weekday = enumType(2);

等同于:

Weekday = Wednesday;

但是,如果试图将一个超出枚举取值范围的值通过强制转换赋给枚举变量,会出现什么结果?

Weekday = enumType(20);

结果将是不确定的,这么做不会出错,但得不到想要的结果。

步骤2——自定义枚举量的值方法/步骤1:

前面讲通过定义

enum enumType {Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday};

枚举量Monday、Tuesday等的值默认分别为0-6,我们可以显式的设置枚举量的值:

enum enumType {Monday=1, Tuesday=2, Wednesday=3, Thursday=4, Friday=5, Saturday=6, Sunday=7};

指定的值必须是整数

方法/步骤2:

也可以只显式的定义一部分枚举量的值:

enum enumType {Monday=1, Tuesday, Wednesday=1, Thursday, Friday, Saturday, Sunday};

这样Monday、Wednesday均被定义为1,则Tuesday=2,Thursday、Friday、Saturday、Sunday的值默认分别为2、3、4、5.

总结:未被初始化的枚举值的值默认将比其前面的枚举值大1。

方法/步骤3:

第二条还说明另外一个现象,就是枚举量的值可以相同。

步骤3——枚举的取值范围方法/步骤1:

前面讲到可以通过强制转换将其他类型值赋给枚举变量:

Weekday = enumType(2);

这是合法的;但是

Weekday = enumType(20);是非法的。

这里涉及枚举取值范围的概念:

枚举的上限是 大于最大枚举量的 最小的2的幂,减去1;

枚举的下限有两种情况:一、枚举量的最小值不小于0,则枚举下限取0;二、枚举量的最小值小于0,则枚举下限是 小于最小枚举量的 最大的2的幂,加上1。

举例来讲:

假如定义 enum enumType1 { First=-5,Second=14,Third=10 };

则枚举的上限是16-1=15(16大于最大枚举量14,且为2的幂);

枚举的下限是-8+1=-7(-8小于最小枚举量-5,且为2的幂);

步骤4——枚举应用方法/步骤1:

个人觉得枚举switch是最好的搭档:

enum enumType{Step0, Step1, Step2}Step=Step0;

//注意这里在声明枚举的时候直接定义了枚举变量Step,并初始化为Step0

switch (Step)

{

case Step0:{...;break;}

case Step1:{...;break;}

case Step2:{...;break;}

default:break;

}

注意事项

在实际应用中,枚举常常用来定义符号常量。

0
范皓翔
范皓翔
初级光能
初级光能

https://blog.csdn.net/hyqsong/article/details/41962455

https://www.cnblogs.com/hanfeihanfei/p/6213195.html

https://baike.so.com/doc/6121029-6334178.html

https://blog.csdn.net/u014527058/article/details/52751488

https://wenda.so.com/q/1387558802062383

所属类别 :

词汇

枚举在C/C++/c#,还有Objective-C中,是一个被命名的整型常数的集合,枚举在日常生活中很常见。例如表示星期的SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY,SATURDAY, 就是一个枚举。枚举的说明与结构和联合相似。

 

基本信息

  • 中文名称

    枚举

  • 外文名称

    enumerate

  • 拼音

    méi jǔ

 

  • 释义

    指一一列举

  • 出处

    《书·无逸》

  • 中文注音

    ㄇㄟˊ ㄐㄨˇ

目录

1词语概念

2常数集合

3数值计算

4枚举排列

折叠编辑本段词语概念

折叠基本信息

词目:枚举

拼音: méi jǔ

中文注音: ㄇㄟˊ ㄐㄨˇ

英文:enumerate[1]

折叠引证解释

一一列举。《北史·恩幸传序》:"其间盗官卖爵,污辱宫闱者多矣,亦何可枚举哉。"《书·无逸》"其在 祖甲 ,不义惟王" 宋 蔡沉 集传:"下文 周公 言,自 殷 王 中宗 及 高宗 及 祖甲 及我 周文王 。及云者,因其先后次第而枚举之辞也。" 清 李渔 《闲情偶寄·词曲上·结构》:"此类繁多,不能枚举。"[1]

折叠编辑本段常数集合

枚举(enum)

枚举在C/C++/c#中,是一个被命名的整型常数的集合, 枚举在日常生活中很常见。

例如表示星期的SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY,SATURDAY, 就是一个枚举。

枚举的说明与结构和联合相似, 其形式为:

enum 枚举名{

标识符[=整型常数],

标识符[=整型常数],

...

标识符[=整型常数]

} 枚举变量;

如果枚举没有初始化, 即省掉"=整型常数"时, 则从第一个标识符开始, 顺

次赋给标识符0, 1, 2, ...。但当枚举中的某个成员赋值后, 其后的成员按依次

加1的规则确定其值。

例如下列枚举说明后, x1, x2, x3, x4的值分别为0, 1, 2, 3。

enum Num{x1, x2, x3, x4}x;

当定义改变成:

则x1=0, x2=0, x3=50, x4=51

注意:

1. 枚举中每个成员(标识符)结束符是",", 不是";", 最后一个成员可省略","。

2. 初始化时可以赋负数, 以后的标识符仍依次加1。

3. 枚举变量只能取枚举说明结构中的某个标识符常量。

例如:

此时, 枚举变量x实际上是7。

枚举类型变量的赋值和使用

枚举类型在使用中有以下规定:

1.枚举值是常量,不是变量。不能在程序中用赋值语句再对它赋值。例如对枚举weekday的元素再作以下赋值: sun=5;mon=2;sun=mon; 都是错误的。

2. 枚举元素本身由系统定义了一个表示序号的数值,从0 开始顺序定义为0,1,2…。如在weekday中,sun值为0,mon值为1, …,sat值为6。

3. 只能把枚举值赋予枚举变量,不能把元素的数值直接赋予枚举变量。如: a=sun;b=mon; 是正确的。而: a=0;b=1; 是错误的。如一定要把数值赋予枚举变量,则必须用强制类型转换,如: a=(enum weekday)2;其意义是将顺序号为2的枚举元素赋予枚举变量a,相当于: a=tue; 还应该说明的是枚举元素不是字符常量也不是字符串常量, 使用时不要加单、双引号。

10个数字,任意取出不相等的5个数字,

谁还记得这个算法的公式????????

用javascript有什么好的计算方法??

m n*(n-1)*(n-2)*...*(n-m+1) n!

C = --------------------------------------------- = --------------------------

n m*(m-1)*(m-2)*...*3*2*1 m!*(n-m)!

这个是公式,但是对枚举作用不大,还是要遍历循环才行.

这就需要一个好的算法

折叠编辑本段数值计算

枚举(pascal)

随着计算机的不断普及,程序不仅只用于数值计算,还更广泛地用于处理非数值的数据。例如:性别、月份、星期几、颜色、单位名、学历、职业等,都不是数值数据。 在其它程序设计语言中,一般用一个数值来代表某一状态,这种处理方法不直观,易读性差。如果能在程序中用自然语言中有相应含义的单词来代表某一状态,则程序就很容易阅读和理解。也就是说,事先考虑到某一变量可能取的值,尽量用自然语言中含义清楚的单词来表示它的每一个值,这种方法称为枚举方法,用这种方法定义的类型称枚举类型

type

daytype=(sun,mon,tue,wed,thu,fri,sat );

C#中的枚举

枚举类型是一种值类型,它用于声明一组命名的常数。

(1)枚举的声明:枚举声明用于声明新的枚举类型。

访问修辞符 enum 枚举名:基础类型

{

枚举成员

}

基 础类型必须能够表示该枚举中定义的所有枚举数值。枚举声明可以显式地声明 byte、sbyte、short、ushort、int、uint、long 或 ulong 类型作为对应的基础类型。没有显式地声明基础类型的枚举声明意味着所对应的基础类型是 int。

(2)枚举成员

枚举成员是该枚举类型的命名常数。任意两个枚举成员不能具有相同的名称。每个枚举成员均具有相关联的常数值。此值的类型就是枚举的基础类型。每个枚举成员的常数值必须在该枚举的基础类型的范围之内。

示例:

产生编译时错误,原因是常数值 -1、-2 和 –3 不在基础整型 uint 的范围内。

(3)枚举成员默认值

在枚举类型中声明的第一个枚举成员它的默值为零。

以后的枚举成员值是将前一个枚举成员(按照文本顺序)的值加 1 得到的。这样增加后的值必须在该基础类型可表示的值的范围内;否则,会出现编译时错误。

示例:

Morning的值为0,Afternoon的值为1,Evening的值为2。

(4)为枚举成员显示赋值

允许多个枚举成员有相同的值.

没有显示赋值的枚举成员的值,总是前一个枚举成员的值+1.

示例

b的值为2,d的值为2.

注意:以上枚举值都不能超过它的基础类型范围。否则会报错.

(5)枚举类型与基础类型的转换

基础类型不能隐式转换为枚举类型

枚举类型也不能隐式转换为基础类型

示例:

(6)System.Enum类型

System.Enum 类型是所有枚举类型的抽象基类,并且从 System.Enum 继承的成员在任何枚举类型中都可用。

System.Enum 本身不是枚举类型。相反,它是一个类类型,所有枚举类型都是从它派生的。

System.Enum 从类型 System.ValueType派生

(7)使用枚举类型

折叠编辑本段枚举排列

折叠1~n全排列

给定一整数n,要按照字典序从小到大的顺序枚举输出前n个数(1-n)的全排列。例如:n=3时,枚举排列结果是:(1,2,3)、(1,3,2)、(2,1,3)、(2,3,1)、(3,1,2)、(3,2,1)。以下是c语言源码实现该算法:

------------------------------------c源码----------------------------------------

折叠可重集全排列

输入数组P,并按字典序输出数组P各元素的全排列到A(注意:P有序),例如P序列为:1 1 2,则对应的排序结果为:(1,1,2)、(1,2,1)、(2,1,1)。以下是该算法的c源码,P数组长度可以自己调整。

0
被禁言 姜思远
姜思远
初级光能
初级光能

一直没怎么用过枚举enum,因为不会用,也不知道他的优点在何处,今天仔细看了看,以后要学着用了,很有必要:
       看一些资料说枚举有助于减少buge,比较好奇,专门了解了下,原因如下
       枚举类型是强类型的,从而保证了系统安全性。枚举可以限定参数的个数,对调用者的行为能更加严格地进行控制。把一些运行期的参数检查放到了编译期,这点很重要。
       
        举个常用的例子,你要表示星期1-7,你可以用int1-7,但是当你把它作为参数的时候,有时后你就给考虑传入0,8的情况.而且用数字表示还需要相应的注释和文档.
       这个时候你定义个一个枚举,名字就叫字面就叫Monday , Tuesday ,....就行,直观,并且值可控.
       eg.  enum  Days {Sat,Sun,Mon,Tue,Wed,Thu,Fri};

       ps: 默认从零开始,然后依次加一。即sat=0;sun=1....fri=6;
       也可在初始化时给其赋值。
       but:若有  enum Datys{sat=3,sun=2,mon,tue,wen,thu,fri}  ,这样会有,mon也=3,即mon=sat。这个不会报错,但是使用的时候会产生问题,不建议使用。
————————————————
版权声明:本文为CSDN博主「克里特」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/hyqsong/article/details/41962455

0
高子健
高子健
新手天翼
新手天翼

暴力枚举法总结

集训快要结束了,按照要求需要写一篇关于枚举的总结,于是在网上也看了许多其他菊苣写的文章,深受启发,但是思来想去感觉又不太系统,于是希望能在吸收那些知识后做一些整理,帮助后面的新人。

 

枚举的基本方法:

  枚举,枚举,顾名思义,就是将所有情况都举出,并判断其是否符合题目条件。所以枚举的基本方法便是分析题意后,找到一个合适的维度列举每一个元素,以完成题目。其中如何找到一个合适的维度来进行枚举便是其中的最大难点。

 

枚举的基本条件:

  首先是时间条件。一般来说主流的OJ当中,1000ms的时间限制下可以运行操作数为10^7以内的运算(通常10^6以内较为保险),所以在采用枚举方法之前最好看一下数据范围,确保整个程序的执行操作数不会超过10^6-10^7这个量级,如果超过了就尝试更换枚举的维度或者使用其他算法吧。

  其次是编程上的实现条件。在编程实现上,一般来说暴力枚举需要两个条件,一是枚举的范围一般需要连续,如果枚举范围是离散的,那么一般很难使用for循环枚举出所有状态,也就不能保证解的完整性(不过有些时候数据看似离散,但实际上可以经过处理变得连续)。第二个条件是枚举内容需要已知,不能在枚举到某个地方的时候出现未知(不过这个一般都被满足)。

 

枚举的优点:

  1.能举出所有情况,保证解为正确解。

  2.能解决许多用其他算法难以解决的问题。

  3.便于思考与编程。

 

例题一:火柴棒等式:

【问题描述】给你n根火柴棍,你可以拼出多少个形如“A+B=C”的等式?等式中的A、B、C是用火柴棍拼出的整数(若该数非零,则最高位不能是0)。用火柴棍拼数字0-9的拼法如图所示:

注意:

     1. 加号与等号各自需要两根火柴棍

     2. 如果A≠B,则A+B=C与B+A=C视为不同的等式(A、B、C≥0)

     3. n根火柴棍必须全部用上

【输入】输入一个整数n(n≤24)。

【输出】输出能拼成的不同等式的数目。 

问题简述:给你n(n<=24)根火柴棒,叫你拼出 “A + B = C”这样的等式,求方案数。

思路:由于题目中已经给出,最多有24根火柴,而等号和加号各用4根的前提下,A\B\C三个数则总共只有20根火柴,数据范围较小,可以用枚举法枚举A、B。这个时候我们发现,0-9这10个数字所用的火柴数为:6,2,5,5,4,5,6,3,7,6,很明显数字1用的火柴棒最少只要2根,不妨让B为1,那么A和C最多可以使用18根火柴,而C>=A,满足条件的A的最大取值为1111。所以枚举A和B的范围是从0~1111。

为了加快速度,可以将0到2222的所有整数需要的火柴棒数目提前算好保存在数组中。

 

代码:

复制代码

#include <iostream>
using namespace std;
int a[2223]={6,2,5,5,4,5,6,3,7,6};
const int b[10]={6,2,5,5,4,5,6,3,7,6};
//计算自然数n所需要的火柴数
int need(int n)
{
    int tmp, num;
    num=0;
    if(n==0) return 6;
    while(n>0) {
        tmp=n%10;
        num+=b[tmp];
        n/=10;
    }
    return num;
}

int main( )
{
    int n,A,B,C,D,sum;
    cin>>n;
    sum=0;
    for(int i=10; i<2223; i++) //预处理
        a[i]=need(i);
    for(int i=0; i<=1000; i++) {
        for(int j=0; j<=1000; j++) {
            A=a[i];   B=a[j];  C=n-4-A-B;
            D=a[i+j];
            if(D==C) sum++;
        }
    }
    cout<<sum<<endl;
    return 0;
}

复制代码

提示:本题使用枚举的优势在于数据范围较小,而且没有合适的其他算法来处理。

 

例题二:计算几何你瞎暴力(玲珑OJ1143)

DESCRIPTION

今天HHHH考完了期末考试,他在教学楼里闲逛,他看着教学楼里一间间的教室,于是开始思考:

如果从一个坐标为 (x1,y1,z1)(x1,y1,z1)的教室走到(x2,y2,z2)(x2,y2,z2)的距离为 |x1−x2|+|y1−y2|+|z1−z2||x1−x2|+|y1−y2|+|z1−z2|

那么有多少对教室之间的距离是不超过RR的呢?

INPUT

第一行是一个整数T(1≤T≤10)T(1≤T≤10), 表示有TT组数据 接下来是TT组数据,对于每组数据: 第一行是两个整数n,q(1≤n≤5×104,1≤q≤103)n,q(1≤n≤5×104,1≤q≤103), 表示有nn间教室, qq次询问. 接下来是nn行, 每行3个整数xi,yi,zi(0≤xi,yi,zi≤10)xi,yi,zi(0≤xi,yi,zi≤10),表示这间教室的坐标. 最后是qq行,每行一个整数R(0≤R≤109)R(0≤R≤109),意思见描述.

OUTPUT

对于每个询问RR输出一行一个整数,表示有多少对教室满足题目所述的距离关系.

SAMPLE INPUT

1 3 3 0 0 0 1 1 1 1 1 1 1 2 3

SAMPLE OUTPUT

1 1 3

HINT

对于样例,1号教室和2号教室之间的距离为3, 1号和3号之间的距离为3, 2号和3号之间的距离为0

 

题意:在一个三维空间中有N个点,q次查询,每次查询给一距离r,求出三维空间中有多少对点之间的哈密顿距离小于r。

思路:一开始的时候如果按照朴素的想法,先离线处理,两两配对求出每两个点之间的距离,之后输出,但是本题中点的数目n的数据较大,如果要全部处理的话需要109左右的操作数,肯定会超时。那么这个时候我们仔细观察后发现,每一个点的范围很小,0<=x,y,z<=10,如果我们通过坐标来遍历每一个点,那么就只需要10^3的复杂度,显然更合适。所以本题也是如此,通过以坐标为单位的枚举,就可以得到最后的结果:

代码:

复制代码

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAX = 10005;
const int MOD = 1e9+7;
const int INF = 0x3f3f3f3f;

int n, q, t, tem;
int a, b, c, x, y, z;
LL aa[35];
LL dex[15][15][15];

int dis(int aa, int bb, int cc, int xx, int yy, int zz)
{
    return abs(aa-xx)+abs(bb-yy)+abs(cc-zz);
}

int main()
{
    scanf("%d",&t);
    while(t--)
    {
        memset(aa, 0, sizeof(aa));
        memset(dex, 0, sizeof(dex));
        scanf("%d%d",&n,&q);
        while(n--)
        {
            scanf("%d%d%d",&x,&y,&z);
            ++dex[x][y][z];
        }
        for(a = 0; a <= 10; ++a)
            for(b = 0; b <= 10; ++b)
                for(c = 0; c <= 10; ++c)
                    if(dex[a][b][c])
                        for(x = 0; x <= 10; ++x)
                            for(y = 0; y <= 10; ++y)
                                for(z = 0; z <= 10; ++z)
                                    if(dex[x][y][z])
                                    {
                                        tem = dis(a, b, c, x, y, z);
                                        if(tem == 0)
                                            aa[tem] += (dex[x][y][z])*(dex[x][y][z]-1)/2;
                                        else
                                            aa[tem] += dex[x][y][z]*dex[a][b][c];
                                    }
        for(int i = 1; i <= 30; ++i)
            aa[i] /= 2;
        for(int i = 1; i <= 30; ++i)
            aa[i] += aa[i-1];
        while(q--)
        {
            scanf("%d",&tem);
            if(tem > 30)
                tem = 30;
            printf("%lld\n",aa[tem]);
        }
    }
    return 0;
}

复制代码

提示:本题采用枚举是因为数据范围的独特性,当数据范围较小的时候,使用枚举的办法是一种好的办法。

0
许金夫
许金夫
初级天翼
初级天翼

我只知道这是数学的计算方法

我要回答