搜索初步-暴力枚举总结与举例

暴力枚举

一.过程:
暴力枚举是将所有情况都进行枚举出,并找到自己的目标的值的过程。
二.方法:
1.用多重循环嵌套,用来寻找在一个数组中的一个值是否与其他的一个或多个值相关。
(这里的相关表示为加减乘除等数学关系)
2.用单层循环嵌套,将某个特殊数值类型在一个范围内的表打出,例如素数表,回文数表,丑数表等;或者统计某个数值类型出现的次数。
3.直接法,将题目意思翻译成编程语言。
三.举例
1.丑数
Description:
只有质数2,3,5,7这几个作为因子的数叫做,丑数,比如前20个丑数是(从小到大来说)
1,2,3,4,5,6,7,8,9,10,12,14,15,16,18,20,21,24和25.
Input
我们给你个n(1<=m<=5842)当输入n为0结束。
Output
输出第n个丑数。每个数一行。
Sample Input
1
2
3
4
11
Sample Output
1
2
3
4
12
思路:
观察描述中的前20个丑数,发现除了1以外的所有丑数都为2,3,5,7的倍数,所以我们只要将2,3,5,7的倍数枚举出来然后存到数组中,再进行排序,最后再找n位置的数组中的元素即可。但衍生出的问题是如何给它们的倍数排序。
方法:先将2,3,5,7的相同倍的倍数都表示出来,然后找其中最小的,将其放置入第二个位置,然后看这个最小的数是谁的倍数,就让谁的倍数加一,以此类推,直到打出整个丑数表。

代码:

#include<bits/stdc++.h>
using namespace std;
int minn(int x1,int x2,int x3,int x4)//找寻4个数的最小值。
{
    int x,y;
    x=min(x1,x2);y=min(x3,x4);
    return min(x,y);
}
int main()
{
    long long str[5845],d2,d3,d5,d7,i,n;
    d2=d3=d5=d7=1;str[1]=1;
    for(i=2;i<=5842;i++)
    {
        str[i]=minn(str[d2]*2,str[d3]*3,str[d5]*5,str[d7]*7);//找到相同倍数和不同倍数时的最小值。
        if(str[i]%2==0)//是谁的倍数谁的倍数就加一。
            d2++;
        if(str[i]%3==0)
            d3++;
        if(str[i]%5==0)
            d5++;
        if(str[i]%7==0)
            d7++;
    }
    while(~scanf("%lld",&n))
    {
        if(n==0)
            break;
        else printf("%lld\n",str[n]);
    }
    return 0;
}

2.牛奶碑文
Descripe:
小伟暑假期间到大草原旅游,在一块石头上发现了一些有趣的碑文。碑文似乎是一个神秘古老的语言,只包括三个大写字母 C、O 和 W。尽管小伟看不懂,但是令他高兴的是,C、O、W的顺序形式构成了一句他最喜欢的奶牛单词“COW”。现在,他想知道有多少次 COW 出现在文本中。
如果 COW 内穿插了其他字符,只要 COW 字符出现在正确的顺序,小伟也不介意。甚至,他也不介意出现不同的 COW 共享一些字母。例如,CWOW 出现了 1 次 COW,CCOW 算出现了2 次 COW,CCOOWW 算出现了 8 次 COW。
Input:
第 1 行为 1 个整数 N。
第 2 行为 N 个字符的字符串,每个字符是一个 C、O 或 W。
Output:
输出 COW 作为输入字符串的字串出现的次数(不一定是连续的)。
提示:答案会很大,建议用 64 位整数(long long)。
Sample Input
6
COOWWW
Smaple Output
6
Hint
对于 50% 的数据满足:N≤60。
对于 100% 的数据满足:N≤100000。
单组输入。
思路:
其实用三重循环嵌套可以解决第一重循环寻找’C’,第二重循环寻找’O’,第三重循环寻找‘W’。但是三重循环的时间复杂度为你的三次方,对于100%的数据N小于等于1e5,O=1e15,机器在1s是无法跑完的。所以我们用另外一种方法,我们从左往右统计C的数量,如果出现O就将该O前所有C的个数赋给O,如果出现W就将该W前所有的O的值赋给W,最后相加每个W所带的值就是最后COW出现的次数,如上做法只需要一次遍历,时间复杂度大大减小。

代码

#include <iostream>
#include<bits/stdc++.h>
using namespace std;
int main()
{
    char str[100005];
    long long sumc,sumo,sumw,n,i,j,k;
    sumc=sumo=sumw=0;
    scanf("%lld",&n);
    for(i=0;i<=n;i++)
    {
        scanf("%c",&str[i]);
        if(str[i]=='C')
            sumc++;
        if(str[i]=='O')
            sumo+=sumc;
        if(str[i]=='W')
            sumw+=sumo;
    }
    if(sumw!=0)
        printf("%lld",sumw);
    else printf("0");
    return 0;
}

3.矩形
Descripe:
在测试超大规模集成电路时,对给定的一个设计,专家要检测元件是否相互遮盖。一个元件可视为一个矩形,假设每个矩形都是水平排列的(边与x轴或y轴平行),所以长方形由最小的和最大的x,y坐标表示。
编程计算完全被覆盖的矩形个数
Input:
输入有多组长方形实例。对每组长方形,第一个数字是长方形的数量,然后是长方形的最小和最大x,y坐标(最小x,最大x,最小y,最大y)。
Output:
对每组输入数据,输出一行,是被完全覆盖的长方形数量。
Sample Input:
3
100 101 100 101
0 3 0 101
20 40 10 400
4
10 20 10 20
10 20 10 20
10 20 10 20
10 20 10 20
Sample Output
0
4
思路:
算出最大X乘以最大Y,最大X乘以最小Y,最小X乘以最小Y,最小X乘以最大Y的面积分别存入4个数组中,并且用一个数组的下标表示每个矩阵出现的次数,避免反复出现在统计时反复统计(这点和Noip中的“珠心算”有异曲同工之妙)。
代码:

#include <iostream>
#include<bits/stdc++.h>
using namespace std;
int main()
{
   int maxx,minx,maxy,miny,s1[1000],s2[1000],s3[1000],s4[1000],a[10000],n,i,j,sum;
    while(~scanf("%d",&n))
    {
        sum=0;
        memset(a,0,10000);
        for(i=0;i<n;i++)
        {
            scanf("%d %d %d %d",&minx,&maxx,&miny,&maxy);
            s1[i]=minx*miny;
            s2[i]=minx*maxy;
            s3[i]=maxx*miny;
            s4[i]=maxx*maxy;
        }
        for(i=0;i<n;i++)
        {
            for(j=i+1;j<n;j++)
            {
                if(s1[i]==s1[j])
                {
                    a[i]++;
                    a[j]++;
                }
                if(s2[i]==s2[j])
                {
                    a[i]++;
                    a[j]++;
                }
                if(s3[i]==s3[j])
                {
                    a[i]++;
                    a[j]++;
                }
                if(s4[i]==s4[j])
      		}
                    a[i]++;
                    a[j]++;
                }
            }
        }
        for(i=0;i<n;i++)//只要不为零,就一定有,我们只要统计是否出现而无需统计其出现了多少次。
        {
            if(a[i]!=0)
                sum++;
        }
        printf("%d\n",sum);
    }
    return 0;
}

注释:题目来源东北林业大学OJ网络。
网址:acm.nefu.edu.cn.
题名为举例名字。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值