暴力枚举
一.过程:
暴力枚举是将所有情况都进行枚举出,并找到自己的目标的值的过程。
二.方法:
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.
题名为举例名字。