列挙とは、百科事典の説明:数学とコンピューターサイエンスの理論では、セットの列挙は、特定の有限シーケンスのセットのすべてのメンバー、または特定のタイプのオブジェクトの数をリストするプログラムです。これら2つのタイプは、多くの場合(常にではありません)重複します。名前付き整数定数のコレクションです。列挙は日常生活で非常に一般的です。たとえば、週を表すSUNDAY、MONDAY、TUESDAY、WEDNESDAY、THURSDAY、FRIDAY、SATURDAYは列挙型です。
単純な理解と列挙は、1つずつ答えようとする問題解決戦略です。
私たちは通常、数学的な方法などの問題を解決する非常に優れた方法を持っています。数学的な方法で問題を解決するには、法則を見つけて式を公式化することがよくあります。数式で直接答えが得られる場合は、基本的に時間の複雑さはないため、数学的方法は非常に明確です。
しかし、現実には、従うことができない多くのルールがあり、どれが本当の答えであるかを確認するために、愚かな方法を1つずつ試す必要がありました。
例:Nより小さい最大の素数を見つけます。この種の問題は数式を見つけることができないため、素数はNに従って計算できます。それでは、N-1が素数かどうかを判断する必要がありますか?N-2は素数ですか?......このようにして、Niが素数かどうかを判断します。これは、いわゆる列挙型のアイデアです。
ここにいくつかの例があります。質問はすべてインターネットからです。
例一
鶏一羽5元、鶏一羽3元、雛3羽1元鶏100羽分100羽購入鶏、鶏、雛はいくつある?
問題を解決するには、列挙メソッドを使用します。3種類の鶏の数を列挙オブジェクトとしてそれぞれx、y、zを設定し、3種類の鶏の総数と鶏の総数を判定条件としてさまざまな鶏を使い果たします。番号。
x + y + z = 100
5*x + 3*y + z/3 = 100
分析1
方程式を解いてこの問題を解くのに多くの推測が必要な場合、コンピュータの利点の1つは、計算速度が特に激しいことです。101ニーズ、我々は問題を解決するためにブルートフォースメソッドを使用する方法がそう3が、コンピュータのための時間の推測では、問題ありません。
手順1:
#include <stdio.h>
int main()
{
int x, y, z;
for( x=0; x <= 100; x++ )
for( y=0; y <= 100; y++ )
for( z=0; z <= 100; z++ )
{
if( 5*x+3*y+z/3==100 && z%3==0 && x+y+z==100 )
{
printf("公鸡 %2d 只,母鸡 %2d 只,小鸡 %2d 只\n", x, y, z);
}
}
return 0;
}
演算結果:
公鸡 0 只,母鸡 25 只,小鸡 75 只
公鸡 4 只,母鸡 18 只,小鸡 78 只
公鸡 8 只,母鸡 11 只,小鸡 81 只
公鸡 12 只,母鸡 4 只,小鸡 84 只
上記のアルゴリズムを振り返って、時間の複雑度がo(n 3)の3層ループを使用しましたが、実際には、この複雑度のアルゴリズムはまったく使用しません。では、このアルゴリズムを引き続き最適化することは可能ですか?
分析2
最初の式、2つの式、3つの未知数を分析してみましたが、それぞれの未知数のドメインを特定できるはずです。だから私は得る:
x <= 20;
y <= 33;
z <=99;
手順2:
#include <stdio.h>
int main()
{
int x, y, z;
for( x=0; x <= 20; x++ )
for( y=0; y <= 33; y++ )
for( z=0; z <= 99; z++ )
{
if( 5*x+3*y+z/3==100 && z%3==0 && x+y+z==100 )
{
printf("公鸡 %2d 只,母鸡 %2d 只,小鸡 %2d 只\n", x, y, z);
}
}
return 0;
}
これは時間の複雑性が変化しなかったが:O(N 3からの場合)が、演算の数は、我々 101 。3 20まで減少33である 15は、操作6回還元について、99。
分析3
次に、x、yを使用してzを表し、サイクル数を減らすことをもう一度試みます。
z = 100 - x - y;
手順3:
#include <stdio.h>
int main()
{
int x, y, z;
for( x=0; x <= 20; x++ )
for( y=0; y <= 33; y++ )
{
z = 100 - x - y;
if( 5*x+3*y+z/3==100 && z%3==0)
{
printf("公鸡 %2d 只,母鸡 %2d 只,小鸡 %2d 只\n", x, y, z);
}
}
return 0;
}
今回は2サイクルのみが使用され、時間の複雑さはo(n 2)で、エネルギーレベルを直接削減しました。また、質問は前回の21 34 100から21 * 34に直接変更され、回数は直接100倍に削減されました。
分析4
中高生、一般に三次線形方程式で問題を行う場合、問題を解決するために消去法を選択し、次にこの問題で直接zを消去することができます。
x + y + z = 100 ①
5x + 3y + z/3 = 100 ②
3 * ①,得:
15x + 9y + z = 300 ③
联立②③,得:
(15x + 9y + z = 300) - (x + y + z = 100)推出 14x + 8y = 200
解得:y = 25 - (7/4)x ④
然后我们将④带入原式
y = 25 - (7/4)x
为了消除分母,我们设:x = 4k,则:
x = 4k;
y = 25 - 7k;
z= 100 - x - y = 75 + 3k;
根据分析②:x <= 20 ,y <= 33,z <=99,且三者皆>=0
得:k=1,2,3
手順4:
#include <stdio.h>
int main()
{
int x, y, z,k;
for( k=0; k <= 3; k++ )
{
x = 4 * k;
y = 25 - 7 * k;
z = 75 + 3 * k;
printf("公鸡 %2d 只,母鸡 %2d 只,小鸡 %2d 只\n", x, y, z);
}
return 0;
}
このようにして、この問題を1サイクルで解決しました。時間計算量は次のとおり前101とO(n)は、4つのだけの操作に問題、2、21 34 100、及び* 34 21、簡単な倍数。
したがって、列挙メソッドを使用する必要がある場合は、プログラムの実行回数を減らして効率を向上させる必要もあります。
例二
完全な3次問題、問題の説明:a 3 = b 3 + c 3 + d 3は完全な3次方程式です。たとえば、12 3 = 6 ^ 3 + 8 3 + 10 3です。
正の整数N(N≤100)のすべての四元数(a、b、c、d)を見つけるプログラムを作成して、a 3 = b 3 + c 3 + d 3とします。ここで、a> 1です。 b、c、d≤N。
#include <stdio.h>
int main()
{
int i,n,a,b,c,d;
scanf("%d",&n);//输入正整数n
for(a=2;a<=n;a++)
for(b=2;b<=a-1;b++)
for(c=b;c<=a-1;c++)
for(d=c;d<=a-1;d++)
if(a*a*a==b*b*b+c*c*c+d*d*d)
printf("a=%d,b=%d,c=%d,d=%d\n",a,b,c,d);
return 0;
}
この問題についても、b、c、dの値の範囲を小さくして、プログラムの動作速度を上げようとしています。
演算結果:
24
a=6,b=3,c=4,d=5
a=12,b=6,c=8,d=10
a=18,b=2,c=12,d=16
a=18,b=9,c=12,d=15
a=19,b=3,c=10,d=18
a=20,b=7,c=14,d=17
a=24,b=12,c=16,d=20