这帮人,要不从网上复制,要不水帖(是友军)
我来给一个比较标准的解释
枚举,由“枚”和“举”俩字组成
“枚”意思是单个
“举”意思是列举
枚举就是将很多可能性统统列出来,最后找出答案
枚举的优点是稳定性强,缺点是时间相对与其他算法较长
例:现在,笼子里有两种动物,一种是鸡,一种是兔,一只兔有四条腿,一只鸡有两条腿
笼子里,可以数出30个头(就是30个动物)和100条腿,问鸡有几只,兔有几只?
分析:这道题属于典型的枚举(当然,数学学好了也能用假设),所以,代码如下:
#include<iostream>
using namespace std;
int main()//框架部分
{
int i,j;//定义两个循环变量i,j用于列举
for(i=1;i<=30;i++)//i从1到30,表示可能有兔的数量
{
j=30-i;//每次循环,保证鸡(j)与兔(i)的和为30;
if(j*2+i*4==100)//判断,如果鸡的只数乘2+兔的只书乘4正好等于100,说明本次循环的鸡与兔的成立
break;//条件成立后,跳出循环
}
cout<<"鸡的只数有"<<j<<"只"<<endl;
cout<<"兔的只数有"<<i<<"只";//输出
return 0;
}
最终结果,鸡有10只,兔有20只
根据样例,我们发现,枚举是一种简单常用易掌握的算法
只要在循环中找到那个可能性即可
PS:本人入堂不就,穷的一批,求采纳,求关注,您的采纳和关注就是对我最大的支持!
枚举
枚举 (enumeration),是值类型的一种特殊形式,是一个被命名的整型常数的集合,它从 System.Enum 继承,并为基础基元类型的值提供备用名称。
枚举类型有名称、基础类型和一组字段。基础类型必须是一个内置的有符号(或无符号)整数类型(如 Byte、Int32 或 UInt64)。字段是静态文本字段,其中的每一个字段都表示常数。所使用的语言给每个字段都分配一个基础类型的特定值。
快速导航
中文名
枚举
定义
被命名的整型常数的集合
外文名
enumeration
类型
目
录
1词语介绍
【词目】:枚举
【拼音】:méijǔ
【释义】:指一一列举。
【语出】:
《书·无逸》:“其在祖甲,不义惟王。”
蔡沈传:“及云者,因其先后次第而枚举之辞也。”
【基本解释】
[enumerate]一一列举
【详细解释】
一一列举。
2常数集合
枚举(enum)
枚举在C/C++/c#中,是一个被命名的整型常数的集合,枚举在日常生活中很常见。
例如表示星期的SUNDAY,MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,
SATURDAY,就是一个枚举。
枚举的说明与结构和联合相似,其形式为:
enum枚举名{
标识符[=整型常数],
标识符[=整型常数],
...
标识符[=整型常数]
}枚举变量;
如果枚举没有初始化,即省掉"=整型常数"时,则从第一个标识符开始,顺
次赋给标识符0,1,2,...。但当枚举中的某个成员赋值后,其后的成员按依次
加1的规则确定其值。
例如下列枚举说明后,x1,x2,x3,x4的值分别为0,1,2,3。
enumNum{x1,x2,x3,x4}x;
当定义改变成:
enumNum
{
x1,
x2=0,
x3=50,
x4
}x;
则x1=0,x2=0,x3=50,x4=51
注意:
1.枚举中每个成员(标识符)结束符是",",不是";",最后一个成员可省略
","。
2.初始化时可以赋负数,以后的标识符仍依次加1。
3.枚举变量只能取枚举说明结构中的某个标识符常量。
例如:
enumNum
{
x1=5,
x2,
x3,
x4
};
enumNumx=x3;
此时,枚举变量x实际上是7。
枚举类型变量的赋值和使用
枚举类型在使用中有以下规定:
1.枚举值是常量,不是变量。不能在程序中用赋值语句再对它赋值。例如对枚举weekday的元素再作以下赋值:sun=5;mon=2;sun=mon;都是错误的。
2.枚举元素本身由系统定义了一个表示序号的数值,从0开始顺序定义为0,1,2…。如在weekday中,sun值为0,mon值为1,…,sat值为6。
main(){
enumweekday
{sun,mon,tue,wed,thu,fri,sat}a,b,c;
a=sun;
b=mon;
c=tue;
printf("%d,%d,%d",a,b,c);
}
3.只能把枚举值赋予枚举变量,不能把元素的数值直接赋予枚举变量。如:a=sun;b=mon;是正确的。而:a=0;b=1;是错误的。如一定要把数值赋予枚举变量,则必须用强制类型转换,如:a=(enumweekday)2;其意义是将顺序号为2的枚举元素赋予枚举变量a,相当于:a=tue;还应该说明的是枚举元素不是字符常量也不是字符串常量,使用时不要加单、双引号。
main(){
enumbody
{a,b,c,d}month,j;
inti;
j=a;
for(i=1;i<=30;i++){
month[i]
j++;
if(j>d)j=a;
}
for(i=1;i<=30;i++){
switch(month[i]
{
casea:printf("%2d%c\t",i,'a');break;
caseb:printf("%2d%c\t",i,'b');break;
casec:printf("%2d%c\t",i,'c');break;
cased:printf("%2d%c\t",i,'d');break;
default:break;
}
}
printf("\n");
}
10个数字,任意取出不相等的5个数字,
谁还记得这个算法的公式????????
用javascript有什么好的计算方法??
mn*(n-1)*(n-2)*...*(n-m+1)n!
C=---------------------------------------------=--------------------------
nm*(m-1)*(m-2)*...*3*2*1m!*(n-m)!
这个是公式,但是对枚举作用不大,还是要遍历循环才行.
这就需要一个好的算法
3数值计算
枚举(pascal)
随着计算机的不断普及,程序不仅只用于数值计算,还更广泛地用于处理非数值的数据。例如:性别、月份、星期几、颜色、单位名、学历、职业等,都不是数值数据。在其它程序设计语言中,一般用一个数值来代表某一状态,这种处理方法不直观,易读性差。如果能在程序中用自然语言中有相应含义的单词来代表某一状态,则程序就很容易阅读和理解。也就是说,事先考虑到某一变量可能取的值,尽量用自然语言中含义清楚的单词来表示它的每一个值,这种方法称为枚举方法,用这种方法定义的类型称枚举类型。
type
daytype=(sun,mon,tue,wed,thu,fri,sat);
C#中的枚举
枚举类型是一种的值类型,它用于声明一组命名的常数。
(1)枚举的声明:枚举声明用于声明新的枚举类型。
访问修辞符enum枚举名:基础类型
{
枚举成员
}
基础类型必须能够表示该枚举中定义的所有枚举数值。枚举声明可以显式地声明byte、sbyte、short、ushort、int、uint、long或ulong类型作为对应的基础类型。没有显式地声明基础类型的枚举声明意味着所对应的基础类型是int。
(2)枚举成员
枚举成员是该枚举类型的命名常数。任意两个枚举成员不能具有相同的名称。每个枚举成员均具有相关联的常数值。此值的类型就是枚举的基础类型。每个枚举成员的常数值必须在该枚举的基础类型的范围之内。
示例:
public enum TimeofDay:uint
{
Morning=-3,
Afternoon=-2,
Evening=-1
}
产生编译时错误,原因是常数值 -1、-2 和 –3 不在基础整型 uint 的范围内。
(3)枚举成员默认值
在枚举类型中声明的第一个枚举成员它的默值为零。
以后的枚举成员值是将前一个枚举成员(按照文本顺序)的值加 1 得到的。这样增加后的值必须在该基础类型可表示的值的范围内;否则,会出现编译时错误。
示例:
public enum TimeofDay:uint
{
Morning,
Afternoon,
Evening
}
Morning的值为0,Afternoon的值为1,Evening的值为2。
(4)为枚举成员显示赋值
允许多个枚举成员有相同的值.
没有显示赋值的枚举成员的值,总是前一个枚举成员的值+1.
示例
public enum Number
{
a=1,
b,
c=1,
d
}
b的值为2,d的值为2.
注意:以上枚举值都不能超过它的基础类型范围。否则会报错.
(5)枚举类型与基础类型的转换
基础类型不能隐式转换为枚举类型
枚举类型也不能隐式转换为基础类型
示例:
public enum Number
{
a,
b,
c,
d
}
class Test
{
public static void Main()
{
int i=Number.a;//错误,要强制类型转换(int)Number.a
Number n;
n=2 //错误,要强制类型转换(Number)2
}
}
(6)System.Enum类型
System.Enum 类型是所有枚举类型的抽象基类,并且从 System.Enum 继承的成员在任何枚举类型中都可用。
System.Enum 本身不是枚举类型。相反,它是一个类类型,所有枚举类型都是从它派生的。
System.Enum 从类型 System.ValueType派生
(7)使用枚举类型
using System;
public enum TimeofDay
{
Morning,
Afternoon,
Evening
} class Test
{
static void WriteGreeting(TimeofDay timeofDay)
{
switch(timeofDay)
{
case TimeofDay.Morning:
Console.WriteLine("good morning");
break;
case TimeofDay.Afternoon:
Console.WriteLine("good afternoon");
break;
case TimeofDay.Evening:
Console.WriteLine("good evening");
break;
}
}
static void Main()
{
WriteGreeting(TimeofDay.Morning);
WriteGreeting(TimeofDay.Evening);
WriteGreeting(TimeofDay.Afternoon);
}
}[1]
4枚举排列
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源码----------------------------------------
#include
#include
voidprint_permutation(intn,int*A,intcur){
inti,j;
if(cur==n){
for(i=0;i
printf("%d",A[i]);
printf("\n");
}
elsefor(i=1;i<=n;i++){
intok=1;
for(j=0;j
if(A[j]==i)
ok=0;
}
if(ok){
A[cur]=i;
print_permutation(n,A,cur+1);//递归调用
}
}
}
voidmain(){
intn;
intA[1000];
printf("inputthen:");
scanf("%d",&n);
print_permutation(n,A,0);
printf("timeused:%.2lf\n",(double)clock()/CLOCKS_PER_SEC);//测试程序运行时间
}
------------------------------------c源码----------------------------------------
可重集全排列
输入数组P,并按字典序输出数组P各元素的全排列到A(注意:P有序),例如P序列为:112,则对应的排序结果为:(1,1,2)、(1,2,1)、(2,1,1)。以下是该算法的c源码,P数组长度可以自己调整。
------------------------------------c源码----------------------------------------
#include
#include
voidprint_permutation(intn,int*P,int*A,intcur){
inti,j;
if(cur==n){
for(i=0;i
printf("%d",A[i]);
printf("\n");
}
elsefor(i=0;i
if(!i||P[i]!=P[i-1]){
intc1=0,c2=0;
for(j=0;j
if(A[j]==P[i])
c1++;
}
for(j=0;j
if(P[i]==P[j])
c2++;
}
if(c1
A[cur]=P[i];
print_permutation(n,P,A,cur+1);//递归调用
}
}
}
}
voidmain(){
intn,m;
intA[1000];
intP;//可以自己修改
inti=0;
while(scanf("%d",&m)==1){
P[i]=m;
i++;
}
n=i;
print_permutation(n,P,A,0);
printf("timeused:%.2lf\n",(double)clock()/CLOCKS_PER_SEC);
}
------------------------------------c源码----------------------------------------
5词条图册
什么是枚举
枚举,顾名思义,就是用最笨的方法,去解决问题(暴力枚举),一个集的枚举是列出某些有穷序列集的所有成员的程序,或者是一种特定类型对象的计数。这两种类型经常(但不总是)重叠。
枚举算法是我们在日常中使用到的最多的一个算法,它的核心思想就是:
枚举所有的可能
枚举法的本质就是从所有候选答案中去搜索正确的解,使用该算法需要满足两个条件:(1)可预先确定候选答案的数量;(2)候选答案的范围在求解之前必须有一个确定的集合。
接下来几道题可以让你更加的了解枚举
1.楼层编号:
题目描述:
小林在NOIP比赛期间住在“新世界”酒店。和其他酒店不一样的是,这个酒店每天都有一个高能的数字t,这个数字在楼层中是不会出现的,以t=3为例,则3、13、31、33等楼层是不存在的,楼层编号为1,2,4,5,……所以实际上的4楼才是3楼
已知小林预定了编号为m层的房间,并且当天高能数字是t,现在他想知道房间所在的真实楼层是多少
输入描述
一行两个整数m和t,1<=m<=100000,0<=t<=9,保证m对t合法
输出描述
一行一个整数,表示真实楼层
样例输入
14 3
样例输出
12
思路:
1.包含这个高能数字的楼层一定不会出现,则有算法如下
bool s(int a,int b){while(a!=0){if(a%10==b){return false;}a/=10;}return true;}
2.用for循环对sum进行累加,若不包含高能数字(即s(i,高能数字)=true)则sum++
for(int i=1;i<=m;i++){if(s(i,t)){sum++;}}cout<<sum
代码:
#include <iostream>using namespace std;bool s(int a,int b){while(a!=0){if(a%10==b){return false;}a/=10;}return true;}int main(){int m,t,sum=0;cin>>m>>t;for(int i=1;i<=m;i++){if(s(i,t)){sum++;}}cout<<sum;return 0;}
2.乘法交换律(暴力枚举)
题目描述
由4个不同的数字,组成的一个乘法算式,它们的乘积仍然由这4个数字组成。
比如:
210 x 6 = 1260
8 x 473 = 3784
27 x 81 = 2187
都符合要求。
如果满足乘法交换律的算式算作同一种情况,那么,包含上边已列出的3种情况,一共有多少种满足要求的算式。
思路:
暴力枚举,四重循环, abcd的值分别从0到9开始 ,然后判断abcd不能相等,然后在不相等的条件下进行乘法运算。乘法运算分为两种情况
a * bcd 和 ab * cd
abcd分别从0-9开始遍历,第一种情况不会出现重复,但第二种情况可能会出现重复,一开始觉得重复会发生在ab大于50 的情况,结果发现 35 和41 也会重复,所以就直接全部遍历再除2解决
判断结果是否和原来的数字组成相同用的最直观的思路,先两个数字都排序,然后依次遍历是否相等,反正就4位。。相同则++计数。
一开始想两种循环嵌套一起,但是分不清ab cd交换律相同的情况,就将两种情况分别讨论。
代码
#include <iostream>#include <algorithm>using namespace std;int main() {int a,b,c,d,answer,count=0 , count1 = 0 ;int org[4];int ans[4];for(a = 0; a<10 ; a++){for(b = 0 ; b < 10; b++){for(c = 0 ; c < 10 ; c++){for (d = 0 ; d < 10 ; d++){if(a!= b && a!=c && a!=d && b!=c && b!=d && c!=d){org[0] = a; org[1] = b ; org[2] = c; org[3] = d;sort(org,org+4);answer = a *(b*100+c*10+d);if(answer >1000 && answer < 9999){ans[0] = answer%10; answer = answer/10;ans[1] = answer%10; answer = answer/10;ans[2] = answer%10; answer = answer/10;ans[3] = answer%10;sort(ans,ans+4);for (int i = 0; i < 4; ++i) {if (ans[i] != org[i]){break;}if(i == 3){count++;}}}}}}}}for(a = 0; a<10 ; a++){for(b = 0 ; b < 10; b++){for(c = 0 ; c < 10 ; c++){for (d = 0 ; d < 10 ; d++){if(a!= b && a!=c && a!=d && b!=c && b!=d && c!=d){org[0] = a; org[1] = b ; org[2] = c; org[3] = d;sort(org,org+4);answer = (a*10+b)*(c*10+d);if(answer >1000 && answer < 9999){ans[0] = answer%10; answer = answer/10;ans[1] = answer%10; answer = answer/10;ans[2] = answer%10; answer = answer/10;ans[3] = answer%10;sort(ans,ans+4);for (int i = 0; i < 4; ++i) {if (ans[i] != org[i]){break;}if(i == 3) {count1++;}}}}}}}}cout<< count+(count1/2);}
3.冰壶比赛
题目描述:
在冰壶比赛中,给出一个目标点P以及一个规定的正整数r。每一局由甲和乙两队轮流投冰壶各8次后,该局比赛结束。此时,哪一方的冰壶最终离目标点P更近,该方得分,另一方不得分。得分方每颗离目标点P距离小于或等于r、位置较另一队所有冰壶都更接近目标点P的冰壶都可以得1分
比赛最多进行10局。双方之间的某局比赛结束后,落后一方可以弃权。此时,比赛不再进行下去
已知每一局结束时,双方的每个冰壶离目标点P的距离以及正整数r,请写一个程序判断两队之间每一局比赛的得分,以及总得分
输入:
第一行一个正整数r
以下有若干行(不超过20行),每一行8个正整数(之间用一个空格间隔)
第二行的第j个数表示第一局比赛结束时,甲方的第j个冰壶距离目标点P的距离
第三行的第j个数表示第一局比赛结束时,乙方的第j个冰壶距离目标点P的距离
……
第2k行的第j个数表示第k局比赛结束时,甲方的第j个冰壶距离目标点P的距离
第2k+1行的第j个数表示第k局比赛结束时,乙方的第j个冰壶距离目标点P的距离
如果有一方中途弃权,则最后一行(偶数行)只有一个整数-1,表示此时发生弃权情况
输出:
输出若干行,每行两个整数,中间以一个冒号间隔,表示每一局比赛甲乙双方的比分(甲得分在前)。最后一行有2个整数,中间以一个冒号间隔,表示甲乙双方比赛的最终得分(甲得分在前)
意思就是,先输入一个“标准”r,有10场比赛,每场比赛打8次,取最好成绩(最近的也就是最小的),再与对手最好成绩比较,比对手低的话一定不得分,比对手高的话还要比标准要小或等于才算得分,也就是说,每场比赛的得分,一定有一方不得分,有可能出现都不得分的情况,若弃权的话直接输出后return 0;即可。最后输出总的比分(计数即可)
主要还是枚举
样例输入
12
5 60 25 74 71 100 3 93
66 75 70 66 52 73 67 14
93 84 74 99 79 64 89 22
65 5 95 59 80 8 35 61
65 61 49 60 58 50 32 85
68 38 96 38 82 64 26 93
74 92 47 21 97 30 45 78
44 99 90 27 3 46 55 34
49 45 83 3 18 1 67 23
60 47 95 81 17 1 87 85
18 74 74 84 29 20 27 71
37 60 26 56 23 65 67 49
57 7 62 92 52 5 10 69
46 97 88 28 76 27 66 7
89 89 94 31 11 20 1 17
19 48 35 6 77 61 45 21
52 11 76 70 73 99 85 55
90 25 20 7 64 24 94 4
3 43 32 74 10 93 35 77
77 100 63 91 10 73 22 57
样例输出
2:0
0:2
0:0
0:1
0:0
0:0
1:0
1:0
0:2
1:0
5:5
样例解释:
可以看到标准为12,
第一局,甲最低3,乙最低14,3<14&&3<=12,甲得分,乙不得分
第二局,甲最低22,乙最低5,5<22&&5<=12,乙得分,甲不得分
第三局,甲最低32,乙最低26,都没有小于等于标准,都不得分
。。。。。。
代码
#include<iostream>#include<string>using namespace std;int main(){int r,i,j;cin>>r;int a[9],b[9],f=0,f1=0,zf=0,zf1=0,min=10000,min1=100000;for(i=1;i<=10;i++){for(j=1;j<=8;j++){cin>>a[j];if(a[1]==-1){cout<<zf<<':'<<zf1;return 0;}}for(j=1;j<=8;j++){cin>>b[j];}for(j=1;j<=8;j++){if(a[j]<min){min=a[j];}}for(j=1;j<=8;j++){if(b[j]<min1){min1=b[j];}}if(min<min1){for(j=1;j<=8;j++){if(a[j]<=r&&a[j]<min1){f++;}}cout<<f<<':'<<f1<<endl;zf=zf+f;f=0;}else if(min1<min){for(j=1;j<=8;j++){if(b[j]<=r&&b[j]<min){f1++;}}cout<<f<<':'<<f1<<endl;zf1=zf1+f1;f1=0;}else{cout<<0<<':'<<0<<endl;}min=10000;min1=10000;}cout<<zf<<':'<<zf1;return 0;}
这里用到了求最小值的方法,还可以改成sort排序后的[0]
好了,今天的内容到现在就结束了,不知道大家有木有听懂呢?听不懂的别忘了在https://blog.csdn.net/weixin_45497223上给我留言,我会第一时间为大家解答的。明天一定要来哦,早上7:00,我们不见不散~~~
度娘:“你怎么不问我?[○・`Д´・ ○]”
枚举,说的简单一点就叫做一个一个可能性去找
比如:你要找1----10000里的质数,你就需要for循环start2到end10000一个一个去找质数
枚举没有什么框架,就是时间复杂度很高,一般在那种没有输入输出的题目中会用
当然枚举也有高深的用法,我不会,勿喷,谢谢


