数据结构与算法之蛮力(穷举)算法
蛮力法是基于计算机运算速度快这一特性,在解决问题时采用的一种“惰性”的策略。这种策略不经过(或者说是经过很少的)思考,把问题的所有情况或所有过程交给计算机去一一尝试,从中找出问题的解。蛮力算法的应用很广。
枚举法(穷举法)是蛮力算法的一种,它对可能解的众多候选解按某种顺序逐一枚举和检验,并从中找出那些符合要求的候选解作为问题的解。
这种方法简单易行,尤其是对于一时想不出更好的解法的问题,不失为一种补救的好方法。但是,这种方法只能解决变量个数有限,而且每个变量可取值个数也很有限的情况,否则会造成“指数爆炸”,在计算机上难以实现。
用枚举法解决问题,通常可以从两个方面进行算法设计。
找出枚举范围:分析问题所涉及的各种情况。
找出约束条件:分析问题的解需要满足的条件,并用逻辑表达式表示。
寻规律问题
寻找规律数字:将1,2,…,9共9个数分成三组,分别组成三个三位数,且使这三个三位数构成1:2:3的比例,试求出所有满足条件的三个三位数。
例如:三个三位数192,384,576满足以上条件。
#include<iostream>
using namespace std;
int main(){
for(int j, i=123;i<327;i++) {
int a[10]={0};
a[i/100]++;a[i%100/10]++;a[i%10]++;
a[i*2/100]++;a[i*2%100/10]++;a[i*2%10]++;
a[i*3/100]++;a[i*3%100/10]++;a[i*3%10]++;
for(j=1;j<10;j++)
if(a[j]!=1) break;
if(j==10)
cout<<i<<" "<<2*i<<" "<<3*i<<endl;
}
}
数字三角形问题
将1,2,······,9共9个数排成下列形态的三角形。
a
b c
d e
f g h i
其中:a~i分别表示1,2,······,9中的一个数字,并要求同时满足下列条件:
(1)a<f<i;
(2)b<d, g<h, c<e
(3)a+b+d+f=f+g+h+i=i+e+c+a=P
程序要求:
根据输入的边长之和P
输出所有满足上述条件的三角形的个数以及其中的一种方案。
#include<iostream>
using namespace std;
int main()
{
int a,b,c,d,e,f,g,h,i,P;
int x[10]={0};
cin>>P;
if(3*P-45<6 || 3*P-45>24) {
cout<<"0";
return 0;
}
for(a=1;a<8;a++)
{
x[a]++;
for(f=a+1;f<9;f++)
{
x[f]++;
for(i=f+1;i<10;i++)
{
x[i]++;
for(b=1;b<9;b++)
{
d=P-b-a-f;
if(x[b]||x[d] ||d<=b) continue;
x[b]++,x[d]++;
for(c=1;c<9;c++)
{
e=P-a-c-i;
if(x[c]|| x[e]||e<=c) continue;
x[c]++,x[e]++;
for(g=1;g<9;g++)
{
h=P-f-g-i;
if(x[g]||x[h]||h<=g)
continue;
cout<<a<<" "<<b<<c<<d<<e<<f<<g<<h<<i<<endl;
}
x[c]--;
x[e]--;
}
x[d]--;
x[b]--;
}
x[i]--;
}
x[f]--;
}
x[a]--;
}
return 0;
}
接水问题
学校里有一个水房,水房里一共装有 m 个龙头可供同学们打开水,每个龙头每秒钟的供水量相等,均为 1。
现在有 n 名同学准备接水,他们的初始接水顺序已经确定。将这些同学按接水顺序从 1到 n 编号,i号同学的接水量为 wi。接水开始时,1 到 m号同学各占一个水龙头,并同时打开水龙头接水。当其中某名同学 j 完成其接水量要求 wj 后,下一名排队等候接水的同学 k马上接替 j 同学的位置开始接水。这个换人的过程是瞬间完成的,且没有任何水的浪费。即j 同学第x 秒结束时完成接水, 则 k 同学第 x+1 秒立刻开始接水。 若当前接水人数 n’不足 m,则只有 n’个龙头供水,其它 m−n’个龙头关闭。
现在给出 n名同学的接水量,按照上述接水规则,问所有同学都接完水需要多少秒。
讲解:
第 1 秒,3 人接水。第 1秒结束时,1、2、3 号同学每人的已接水量为 1,3 号同学接完水,4 号同学接替 3 号同学开始接水。
第 2 秒,3 人接水。第 2 秒结束时,1、2 号同学每人的已接水量为 2,4 号同学的已接水量为 1。
第 3 秒,3 人接水。第 3 秒结束时,1、2 号同学每人的已接水量为 3,4 号同学的已接水量为 2。4号同学接完水,5 号同学接替 4 号同学开始接水。
第 4 秒,3 人接水。第 4 秒结束时,1、2 号同学每人的已接水量为 4,5 号同学的已接水量为 1。1、2、5 号同学接完水,即所有人完成接水。
总接水时间为 4 秒。
输出样式
water.in
8 4
23 71 87 32 70 93 80 76
water.out
163
#include <iostream>
using namespace std;
int main(){
int w[10000]={0},l[100]={0};
int n,m,i,j,k=0;
cin>>n>>m;
for(i=0;i<n;i++)
cin>>w[i];
for(int i=0;i<m;i++)
l[i]=w[i];
j=m;
for(i=1;;i++) {
for(int f=0;f<m;f++) {
l[f]--;
if(l[f]==0 ){
if(j<n){
l[f]=w[j];
j++;
}
k++;
}
}
if(k==n)
break;
}
cout <<i<<endl;
}