算法基础---枚举案例

来源:互联网 发布:网络赚钱的门路2017 编辑:程序博客网 时间:2024/05/16 06:12

**

枚举

**

基于逐个尝试答案的一种问题求解策略
枚举算法的思想是:将问题的所有可能的答案一一列举,然后根据条件判断此答案是否合适,保留合适的,丢弃不合适的。在C语言中,枚举算法一般使用while循环实现。使用枚举算法解题的基本思路如下所示。

(1)确定枚举对象、枚举范围和判定条件; (2)逐一枚举可能的解,验证每个解是否是问题的解(枚举的同时一定要避免重复)。
枚举算法一般按照如下三个步骤进行。 (1)题解的可能范围,不能遗漏任何一个真正解,也要避免有重复。
(2)判断是否是真正解的方法(就是传说中的筛选法进行判断)。 (3)使可能解的范围降至最小,以便提高解决问题的效率。

例子:
难度系数1颗星;

百钱买百鸡问题:公鸡每只5元,母鸡每只3元,小鸡3只1元,用100块钱买100只鸡,问公鸡,母鸡,小鸡各多少只?

#include <iostream>int main(){    int x,y,z;//三个变量分别为公鸡,母鸡,小鸡的数量    for(x=0;x<=20;x++)//公鸡最多20只    {        for(y=0;y<=33;y++)//母鸡最多33只        {            z=100-x-y;//小鸡的数量            if (z%3==0 && x*5+y*3+z/3==100)//小鸡3只一元,所以小鸡数量应该是3的倍数                printf("公鸡%d只,母鸡%d只,小鸡%d只\n",x,y,z);        }    }      return 0;}

难度系数1颗星;

完美立方
描述:
形如a3= b3 + c3 + d3的等式被称为完美立方等式。例如 123= 63 + 83 + 103。编写一个程序,对任给的正整数N (N≤100),寻找所有的四元组(a, b, c, d),使得a3 = b3 + c3 + d3,其中a,b,c,d 大于 1, 小于等于N,且 b<=c<=d。
输入
一个正整数N (N≤100)。
输出
每行输出一个完美立方。输出格式为: Cube = a, Triple = (b,c,d)

  • 样例输入
    24
  • 样例输出
    Cube = 6, Triple = (3,4,5)
    Cube = 12, Triple = (6,8,10)
    Cube = 18, Triple = (2,12,16)
    Cube = 18, Triple = (9,12,15)
    Cube = 19, Triple = (3,10,18)
    Cube = 20, Triple = (7,14,17)
    Cube = 24, Triple = (12,16,20)

由题目就可以知道,每一个未知数都有一个取值范围;
其中:
a的取值范围是:1

#include <iostream>using namespace std;int main(){    int N = 0;    int a,b,c,d;    cin>>N;//获取给定的正整数N    for(a = 2;a<=N;a++){        for(b = 2;b<a;b++){            for(c = b;c<a;c++){                for(d = c;d<a;d++){                    if(a*a*a == b*b*b+c*c*c+d*d*d)//条件                        cout<<"Cube "<<a<<",  Triple = ("<<b<<","<<c<<","<<d<<")"<<endl;                }            }        }    }    return 0;}

难度系数2颗星;
生理周期
人有体力、情商、智商的高峰日子,它们分别每隔 23天、28天和33天出现一次。对于每个人,我们想 知道何时三个高峰落在同一天。给定三个高峰出现 的日子p,e和i(不一定是第一次高峰出现的日子), 再给定另一个指定的日子d,你的任务是输出日子d 之后,下一次三个高峰落在同一天的日子(用距离d 的天数表示)。例如:给定日子为10,下次出现三 个高峰同一天的日子是12,则输出2。

输入
输入四个整数:p, e, i和d。 p, e, i分别表示体力、情感和 智力高峰出现的日子。d是给定的日子,可能小于p, e或 i。 所有给定日子是非负的并且小于或等于365,所求的日子小于 或等于21252。
输出
从给定日子起,下一次三个高峰同一天的日子(距离给定日子的天数)。

输入样例
0 0 0 0
0 0 0 100
5 20 34 325
4 5 6 7
283 102 23 320
203 301 203 40
-1 -1 -1 -1

输出样例
Case 1: the next triple peak occurs in 21252 days.
Case 2: the next triple peak occurs in 21152 days.
Case 3: the next triple peak occurs in 19575 days.
Case 4: the next triple peak occurs in 16994 days.
Case 5: the next triple peak occurs in 8910 days.
Case 6: the next triple peak occurs in 10789 days.

内容提取:
//体力:p;
//情商:e;
//智商:i;
//给定的三个高峰出现的日子p,e和i(不一定是第一次高峰出现的日子);
//日子:d;再给定另一个指定的日子d,你的任务是输出日子d 之后,下一次三个高峰落在同一天的日子(用距离d 的天数表示)。

#include <iostream>//#define N 21252using namespace std;int main(){    int k = 0;    int p,e,i,d;    while(cin>>p>>e>>i>>d&&p!=-1){//输入日子;    for(k =d+1;(k-p)%23;k++);//找出第一个体力高峰期的日子(储存在k中),以后每23天就是一个高峰期,这是可以确定的;    for(;(k-e)%28;k+=23);//找出体力和情感的高峰期日子;    for(;(k-i)%33;k+=23*28);//找出体力,情感,智力的高峰期的日子;    cout <<"距离d:"<<k-d<<endl;    }    return 0;}难度系数3颗星;

称硬币
有12枚硬币。其中有11枚真币和1枚假币。假币和真 币重量不同,但不知道假币比真币轻还是重。现在, 用一架天平称了这些币三次,告诉你称的结果,请你 找出假币并且确定假币是轻是重(数据保证一定能找 出来)。

输入
第一行是测试数据组数。
每组数据有三行,每行表示一次称量的结果。银币标号 为A-L。每次称量的结果用三个以空格隔开的字符串表示: 天平左边放置的硬币 天平右边放置的硬币 平衡状态。其 中平衡状态用up'',down”, 或 “even”表示, 分 别为右端高、右端低和平衡。天平左右的硬币数总是相等 的。
输出
输出哪一个标号的银币是假币,并说明它比真币轻还是重。

输入样例
1
ABCD EFGH even
ABCI EFJK up
ABIJ EFGH even
输出样例
K is the counterfeit coin and it is light.

#include <iostream>#include <cstring>using namespace std;char zuo[3][6] = {0};//表示左边的每组有三组数据char you[3][6] = {0};//表示右边的每组有三组数据char balance[3][6] = {0};//表示每一小组的结果;    //判断ch是轻吗?;bool bool_type_light(char ch,bool light)//假设为轻是true,否则为false,light 为真表示假设假币为轻,否则表示假设假币为重{    char *Left= NULL,*Right = NULL;    for( int i = 0;i<3;i++){        if(light){            Left = zuo[i];            Right = you[i];        }        else{//如果是重的,可以将其转换到轻的来考虑            Left = you[i];            Right = zuo[i];        }        switch(balance[i][0]){            case 'u':                if(strchr(Right, ch) == NULL){//找不到这个字符;                    return false;                }                break;            case 'd':                if ( strchr(Left,ch) == NULL)                    return false;                break;            case 'e':                if( strchr(Left,ch) || strchr(Right,ch))                    return false;                break;        }    }    return true;}int main(){    int i = 0;//表示组数    cin>>i;    while(i--){        for(int i = 0;i<3;i++){//输入一个大组的值,和三小组的参数;            cin>>zuo[i]>>you[i]>>balance[i];        }        for(char ch = 'A';ch<='L';ch++){            if(bool_type_light(ch, false)){//传入为重的信号                cout<<ch<<" is the counterfeit coin and it is heavy"<<endl;                break;            }            else if(bool_type_light(ch, true)){                cout <<ch<<" is the counterfeit coin and it is light"<<endl;                break;            }        }    }    return  0;}

总结:
1.明白自己使用的是什么方法求解;
2.细节方面需要多思考,就比如本道题的假设是轻的为true 重的是false;
以及在处理天平时候的小技巧:将重的情况和轻的情况融合在一起,可以减少代码的重复;
3.在处理数据或者信息时,最好是细心处理每一种小小的条件;
4.将枚举的一些优点应用上,枚举虽然是一种很方便的算法,不过也要切合实际应用。
5.在应用枚举时候注意每一种判断的条件应该尽量别有重复;如果有重复,就用已经有的知识将其剔除;保证时间的复杂度尽可能的小;

还有一个例题就是熄灯问题;
难度系数可能更高;
参考网页:http://blog.csdn.net/qq_37954111/article/details/78304263

原创粉丝点击