没有套路的暴力枚举

有一类问题可以采用一种盲目的搜索方法,在搜索结果的过程中,把各种可能的情况都考虑到,并对所得的结果逐一进行判断,过滤掉那些不符合要求的,保留那些符合要求的,这种方法叫枚举算法。
并不是所有的问题都可以使用枚举算法来求解,只有当问题的所有可能解的个数不太多时,并在可以接受的时间内得到问题的所有解,才有可能使用枚举算法 。

例题

1.林大 OJ 8 二倍的问题
第一个方法,简单排序

#include <bits/stdc++.h>

using namespace std;

int main()
{
  int n,a[20],ans,j;
  scanf("%d",&n);
  for(int i=1;i<=n;i++)
 {
    j=0;
    scanf("%d",&a[j]);
    while(a[j]!=0)
    {
       j++;
       scanf("%d",&a[j]);
    }
       sort(a,a+j);
       ans=0;
       for(int x=0;x<j;x++)
         for(int i=x+1;i<j;i++)
            {
               if(a[i]==a[x]*2)
                  ans++;
            }
   printf("%d\n",ans);
 }
    return 0;
}

第二个方法,桶排序,但是我这个桶排序码得很麻烦,还用了二维数组,大家就参考参考
对于桶排序的理解

在这里插入图片描述
比如这个数值为X,就把它存放在X桶中,我们需要设置桶的数量(即排序的范围),把数据放到与之匹配的桶里,改变记录桶有多少个数据的变量(一定要在装数据之前初始化),输出时要遍历所有桶,选数据不为0的数据输出,按编号输出即可。

#include <bits/stdc++.h>
#include <iostream>
using namespace std;

int n,a[100][100],j,i,b[100][100],p[1000],maxx[1000],m;   //二维数组,桶排序

int main()
{
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        j=0;
        maxx[i]=-1111; //随便写一个负值就可
        scanf("%d",&a[i][j]);//输入第i行第j个数值
        while(a[i][j]!=0)//不等于0的话,下面接着循环输入
        {
            b[i][a[i][j]]=1; //表示第i行数值为a[i][j](即第i行第j个数值 )的个数为1        
            if(a[i][j]>maxx[i])
            {
               maxx[i]=a[i][j];
               //求出最大值,即最大的桶
            }
            j++;     //第i行元素+1
            scanf("%d",&a[i][j]);
        }
    }
    for(i=1;i<=n;i++)
    {
        p[i]=0;                           
        for(j=0;j<=maxx[i];j++)
        {
            if(b[i][a[i][j]*2]==1)   //第i行中2倍的a[i[][j]仍然存在
                p[i]++;  
        }
        printf("%d\n",p[i]);
    }
    return 0;
}

2.林大OJ 573 大乐透
理解
定义六个循环变量,i1,i2,i3,i4,i5,i6。a[i1]-a[i6]为从k个数中取出的六个数,它们之间的关系为i1<i2<i3<i4<i5<i6按顺序输出。因此a[i1]只能为前k-5个数中的一个, a[i2]只能为前k-4个数中的一个……最后依次输出a[i1]-a[i6]。

#include <iostream>
#include <bits/stdc++.h>
using namespace std;

int main()
{
    int a[100],i,k;
    scanf("%d",&k);
    while(k!=0)
    {
        for(i=1;i<=k;i++)
            scanf("%d",&a[i]);

        for(int i1=1;i1<=k-5;i1++)
            for(int i2=i1+1;i2<=k-4;i2++)
                for(int i3=i2+1;i3<=k-3;i3++)
                    for(int i4=i3+1;i4<=k-2;i4++)
                        for(int i5=i4+1;i5<=k-1;i5++)
                            for(int i6=i5+1;i6<=k;i6++)
                                printf("%d %d %d %d %d %d\n",a[i1],a[i2],a[i3],a[i4],a[i5],a[i6]);

        scanf("%d",&k);
    }

    return 0;
}

3.林大 OJ 572 密码箱
理解
他已经试到第n个了,接下来从n+1试起,分为 一位数 两位数 三位数 情况讨论,一位数前面补上00,两位数前面补上0

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
nt main()
{

 int n;
 while(scanf("%d",&n)!=-1)
 {
    for(int i=n+1;i<1000;i++)//简单的依次网上循环
    {
        if(i<10)
        printf("00%d\n",i);
        if(10<=i&&i<100)
        printf("0%d\n",i);
        if(i>=100)
        printf("%d\n",i);
    }
 }
    return 0;
}

4.林大 OJ 193 字符串统计
理解
暴力查找每一个字符是否为数字即可

#include <iostream>
#include <bits/stdc++.h>
using namespace std;

int main()
{

 int n,k,j;
 char a[101];
 while(scanf("%d",&n)!=EOF)
 {
    for(int i=1;i<=n;i++)   //循环输入每行
     {
         scanf("%s",a);
         j=0;
         k=0;
         while(a[j]!='\0')
         {
             if('0'<=a[j]&&a[j]<='9')
                 k++//统计数字数量
                 
             j++;
         }
       printf("%d\n",k);
     }
 }
 return 0;
}

5.林大OJ 574 丑数
理解
第一个丑数为“1”,后面的每一个丑数都是前面的丑数乘 2,3,5,7
每一个丑数乘上2,3,5,7,成为另一个丑数
x2,x3,x5,x7:xm位置前的丑数已乘过m,
x2:第一次为1,若x2所在位置的丑数已被乘2,则x2需向后移,x3,x5,x7依此类推
每次找丑数就是找到2a[x2],3a[x3],5a[p5],7a[x7]的最小值,
判断n位置的丑数属于哪种类型,说明xm已乘过m,xm位置+1

#include <iostream>
#include <bits/stdc++.h>
using namespace std;

int x2,x3,x5,x7;
int a[5900];
int main()
{
    int i,n;
    a[1]=1;
    x2=x3=x5=x7=1;
    for(i=2;i<=5842;i++)
    {
        a[i]=min(min(a[x2]*2,a[x3]*3),min(a[x5]*5,a[x7]*7));//对获取的丑数进行排序
        if(a[i]%2==0) x2++;
        if(a[i]%3==0) x3++;
        if(a[i]%5==0) x5++;
        if(a[i]%7==0) x7++;
    }
    scanf("%d",&n);
    while(n!=0)
    {
        printf("%d\n",a[n]);
        scanf("%d",&n);
    }
    return 0;
}

6.;林大OJ 575矩形
理解
在纸上画两个矩形,观察坐标的关系
先锁定每个矩形,循环暴力枚举其他矩形(包括它自己)能否覆盖自己 若能 +1

#include <iostream>
#include <bits/stdc++.h>
using namespace std;

struct ju
{
    int x1,x2,y1,y2;
};

int main()
{
    ju p[1000];
    int n,k,sum,i,j;
    while(scanf("%d",&n)!=EOF)
    {
        sum=0;
        for(i=1;i<=n;i++)
            scanf("%d %d %d %d",&p[i].x1,&p[i].x2,&p[i].y1,&p[i].y2);
        for(i=1;i<=n;i++)
        {
            k=0;
            for(j=1;j<=n;j++)
            {
                if(p[i].x1>=p[j].x1&&p[i].x2<=p[j].x2&&p[i].y1>=p[j].y1&&p[i].y2<=p[j].y2)
                    k++;
            }
            if(k==n)
                sum++;
        }
        printf("%d\n",sum);
    }
    return 0;
}

7.林大OJ 1639 抽奖

#include <iostream>
#include <bits/stdc++.h>
using namespace std;

int main()
{
    int n,a[100],i,j,num;
    scanf("%d",&n);
    j=0;
    for(i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }                       //循环输入所有号码
    scanf("%d",&num);
    for(i=1;i<=n;i++)
    {
        if(num==a[i])  //查找是否有中奖号码      
        {
            printf("%d",i);
        }
        if(num!=a[i])
            j++;
    }
    if(j==n)    //找了n个都没有相同号码,即没有中奖
        printf("0");
    return 0;
}

8.林大 OJ 比身高
理解
循环查找他前面和他后面每个人的身高是否比他高,计算他前面和他后面比他高的人数

#include <iostream>
#include <bits/stdc++.h>
using namespace std;

int main()
{
    int n,i,a[1001],j,p,q,t,x;
    scanf("%d",&n);
    t=0;
    for(i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    for(i=1;i<=n;i++)     
    {
        p=0;q=0;
        for(j=i-1;j>0;j--) //从他前面的人向前循环到第一个人
            if(a[j]>a[i])
          p++;    //统计比他高人数
        }
        for(x=i+1;x<=n;x++)  //从他后面的人向后循环到最后一个人
        {
            if(a[x]>a[i])
                q++;    统计比他高人数
        }
        if(p==q)
            t++;
    }
    printf("%d",t);
    return 0;
}

9.林大OJ 1642 楼层编号
理解
**
穷举楼层编号,判断数字是否含高能数字,将所有含高能数字t的楼层计数存储在k中
假设一个数字123456,将它的每一位分离,6最好办,123456%10=6,之后可以先除10,123456/10=12345,再进行模十运算,12345%10=5…
这样子就能把所有的位数找出来,判断是否有t**

#include <iostream>
#include <bits/stdc++.h>
using namespace std;

int main()
{
   int t,m,k,p,s;
   scanf("%d %d",&m,&t);
   k=0;
   for(int i=1;i<=m;i++)
   {
     s=i;
     while(s>0)  //该循环为循环判断每一位是否等于高能数字
     {
         p=s%10;  //取余
         if(p==t)
         {
           k++;
           break;
         }
         s=s/10;  //取模
     }
   }
   printf("%d",m-k);
  return 0;
}

10.林大OJ 1643 比例简化
理解
利用gcd求出最大公约数,要使分子分母互质,最大公约数为1,让分子分母均从1取到L,判断每次情况下分子分母的最大公约数是否为1,即是否互质,循环找出差值最小的分子分母

#include <iostream>
#include <bits/stdc++.h>
using namespace std;

int gcd(int a,int b)
{
    return b?gcd(b,a%b):a;
}             //求最大公约数

int main()
{
    double minn,k1,k2,A,B;
    int x,y,i,L,j;
    minn=10086;//随便设一个数就可
    scanf("%lf %lf %d",&A,&B,&L);
    for(i=1;i<=L;i++)
    {
        for(j=1;j<=L;j++)
        {
            if(gcd(i,j)==1)
            {
                k1=1.0*i/j;
                k2=1.0*A/B;
                if(k2<=k1&&k1-k2<minn)
                {
                    minn=k1-k2;
                    x=i;
                    y=j;
                }
            }
        }

    }
    printf("%d %d",x,y);
    return 0;
}


11.林大OJ 1644奶牛碑文
理解
*因为只有 3 个字母,‘O在中间位置,所以可以穷举字符串中的每一个“O”,假设位置 i,然后分别计算其左边“C” 的个数 c[i] 和右边“W” 的个数 w[i],再利用乘法原理进行计数 c[i]w[i],每次把答案累加

#include <iostream>
#include <bits/stdc++.h>
using namespace std;


long long n,k,p[111111],q[111111],s,f,sum,i;
char a[111111];
int main()
{
    scanf("%lld",&n);
    scanf("%s",a);
    for(i=0;i<n;i++)
    {
        if(a[i]=='C')  //从前往后查找C
            f++;
        p[i]=f;        //记录i位置前的C有f个
    }
    for(i=n-1;i>=0;i--)  //从后往前查找W
    {
        if(a[i]=='W')
            s++;       
        q[i]=s;       //记录i位置后的W有s个
    }
    for(i=0;i<n;i++)
    {
        if(a[i]=='O')
         sum=sum+p[i]*q[i];
    }
    printf("%lld",sum);
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值