基礎算法枚舉法

這幾天刷的算法好幾次都提到了枚舉法,雖然很早知道這個詞,但是對枚舉的概念是迷迷糊糊的,今天特意查了一下。

枚舉法,也稱爲列舉法、窮舉法,是暴力策略的具體體現,又稱爲蠻力法。

枚舉法的基本思想是: 逐一列舉問題所涉及的所有情形,並根據問題提出的條件檢驗哪些是問題的解,哪些應予排除。


枚舉模式:

1)區間枚舉

對於有明確範圍要求的實際案例,通過枚舉循環的上下限控制枚舉區間,而在循環體中完成各個運算操作,然後根據所求解的具體條件,應用選擇結構實施判別與篩選,求得所要求的解。

n = 0

for(k = 區間下限;k <= 區間上限;k++){

    運算操作序列

    if(約束條件){

          System.out.println(滿足要求的解);

          n++;

    }

}

System.out.println(解的個數);


2) 遞增枚舉

有些問題沒有明確的範圍限制,可根據問題的具體情況試探性地從某一起點開始增值枚舉,對每個數進行操作與判別,若滿足條件則輸出結果;

k = 0;

while(true){

    k++;

    運算操作序列

    if(約束條件){

        System.out.println(滿足要求的解);

        return;

    }

}

枚舉的意義:

1) 可以充分利用計算機的速度,解決一些常見問題

2) 如果問題的規模不大,使用枚舉,運算速度是可以接收的。

3) 枚舉可作爲某類問題時間性能的底線,用來引出同樣問題的更高效率的算法。


枚舉的實施步驟:

1) 根據問題的具體情況確定枚舉量(簡單變量或數組)

2) 根據問題的具體清空確定枚舉範圍,設置枚舉循環

3) 根據問題的具體要求確定篩選(約束)條件

4) 設計枚舉程序並運行、調試,對運行結果進行分析與討論。

比如:

使用枚舉法解決“填寫運算符問題”
1,問題描述:在下面的算式中,添加“+”、“-”,“*”,“/”,4個運算符,使得這個式子成立。
5  5  5  5  5=5
2,算法分析:
上述式子左側有5個數字,一共需要4個運算符。根據題目要求,兩個數字之間的運算符只能有4中選擇。在 具體編程時,可以通過循環來填入各種運算符,然後再判斷算式左側的值是否等於右側的值。並保證,當填入的 是除號時,則右側的數不能爲0,並且乘除的優先級高於加減的優先級。
 

#include<iostream>
 
int main()
{
	int j, i[5];		// 循環變量,數組i用來表示4個運算符
	int sign;			// 累加運算時的符號;
	int result;			// 保存運算式子的結果值
	int count=0;		// 計數器,統計符合條件的方案
	int num[6];			// 保存操作數
	float left, right;  //保存中間結果
	char oper[5] = { ' ','+','-','*','/' };   //運算符
 
	printf("輸入5個數,之間用空格隔開:");
	for (j = 1; j <= 5; j++)
		scanf_s("%d",&num[j]);
	printf("輸入結果:");
	scanf_s("%d",&result);
	//注:這裏i[1]代表的第一個運算符的意思,i[1]=1代表第一個運算符是“+”,i[1]=2代表第一個運算符是“減”,i[1]=3代表第一個運算符是“-”,i[1]=4代表第一個運算符是“/”
	//注:這裏i[2]代表的第二個運算符的意思,i[2]=1代表第二個運算符是“+”,i[2]=2代表第二個運算符是“減”,i[2]=3代表第二個運算符是“-”,i[2]=4代表第二個運算符是“/”
	//i[3],i[4]依次類推。
	for (i[1]=1; i[1]<=4; i[1]++)    //循環4種運算符,1表示+,2表示-,3表示*,4表示/
	{
		if ((i[1]<4) || (num[2] != 0))	//運算符若是/,則第二個運算數不能爲0,(注:“||”是或運算,兩個條件至少要有一個成立,即第一個運算符爲/時,第二個運算數不爲0)
		{
			for (i[2]=1; i[2]<=4; i[2]++)
			{
				if ((i[2]<4)||(num[3]!= 0))		//當第二個運算符爲/時,第三個運算數不爲0
				{
					for (i[3] = 1; i[3] <= 4; i[3]++)
					{
						if ((i[3] < 4) ||( num[4] != 0))	//當第三個運算符爲/時,第四個運算數不爲0
						{
							for (i[4] = 1; i[4] <= 4; i[4]++)
							{
								if ((i[4] < 4) || (num[5] != 0))	//當第四個運算符爲/時,第五個運算數不爲0
								{
									left = 0;
									right = num[1];
									sign = 1;
									//使用case語句,將4種運算符填到對應的空格位置,並進行計算
									for (j = 1; j <= 4; j++)
									{
										switch (oper[i[j]])
										{
										case '+':
											left = left + sign*right;
											sign = 1;
											right = num[j + 1];
											break;
										case '-':
											left = left + sign*right;
											sign = -1;
											right = num[j + 1];
											break;
										case '*':
											right = right*num[j + 1];
											break;
										case '/':
											right = right / num[j + 1];
											break;
										}
									}
									//開始判斷,如果運算式子的結果和輸入的結果相同,則表示找到一種算法,並輸出這個解
									if (left + sign*right == result)
									{
										count++;
										printf("%3d:",count);
										for (j = 1; j <= 4; j++)
											printf("%d%c",num[j],oper[i[j]]);
										printf("%d=%d\n",num[5],result);
									}
								}
							}
						}
 
					}
				}
			}
		}
	}
	if (count == 0)
		printf("沒有符合要求的方法!\n");
	system("pause");
	return 0;
}

運行結果:

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章