暴力搜尋演算法淺顯易懂
阿新 • • 發佈:2018-12-17
基礎演算法之 暴力搜尋
演算法說明
暴力演算法也叫蠻力演算法,之所以稱為暴力,是因為該演算法是列舉當前所有出現的情況, 從而得到需要的情況。該演算法可以求的一些情況較少的問題的解,若問題規模太大,該演算法便不適用。
演算法分析
若給定一個集合 α ,求得該集合的所有子集,求得的子集即為某種情況,列出所有子集及是暴力演算法。比如給定一個數組 [1, 3, 5] ,其所有子集為 [ ],[ 1 ],[ 3 ],[ 5 ],[ 1, 3 ],[ 1, 5 ], [ 3, 5 ], [ 1, 3, 5 ] 共八種情況。對於一個元素數量為 n 的集合來說,其子集數目為 2 的 n 次方。證明為: 對於集合中的每個元素,都有選擇或者不選擇兩種情況,則 全部情況為 2 的 n 次方,該證明即為演算法的核心。
問題示例
揹包問題
給定一定數量的物品,每個物品都有其重量和價值,給定一個容量為 c 的揹包,用該揹包裝物品,求 裝的物品價值之和為最大的情況。
問題分析
設集合 A ,其元素為每個物品,利用暴力搜尋演算法列出集合 A 的所有子集,在其子集中找到物品價值之和最大的情況即可。對於該問題選擇的資料結構,在此我用的是一個一維陣列存放物品的重量,另一個一維陣列存放物品的價值,對應下標即可。
程式碼示例(C語言)
#include<stdio.h> int goods_all = 5; /* 物品數量 */ int goods_weight[5] = {1, 3, 6, 8, 12}; /* 物品的重量 */ int goods_value[5] = {1, 4, 8, 10, 20}; /* 物品的價值 */ int package = 20; /* 揹包容量 */ int maxValue = 0; /* 當前最大價值(後面用到)*/ int choose[5]; /* 存放最優方案的物品下標 */ /* 輸出結果函式 */ void outputResult() { for (int i = 0; i < goods_all && choose[i] != -1; i++) { printf("重量:%d,價值:%d\n", goods_weight[choose[i]], goods_value[choose[i]]); } } /* 存放當前最優方案(不斷的更新 choose 陣列) @param goods_list[] 當前的選擇項陣列 @param goods_num 當前的選擇項 數目 */ void storeChoose(int goods_list[], int goods_num){ for (int i = 0; i < goods_all; i++) choose[i] = -1; for (int i = 0; i < goods_num; i++) choose[i] = goods_list[i]; } /* 暴力列舉所有方案(遞迴實現) @param goods_list 存放當前方案的陣列 @param goods_num 當前選擇的物品數目 @param goods_index 當前選擇或不選擇的物品下標 */ void chooseGoods(int goods_list[],int goods_num, int goods_index){ /* 當物品的下標到最後一個物品時,即列舉完畢 , 此時 遍歷當前方案 goods_list[], 若當前方案價值 大於 當前的 maxValue ,則重寫 choose陣列 */ if (goods_index == goods_all) { int value = 0, weight = 0; for (int i = 0; i < goods_num; i++) { weight += goods_weight[goods_list[i]]; value += goods_value[goods_list[i]]; } if (weight <= package && value > maxValue) { storeChoose(goods_list, goods_num); maxValue = value; } }else { /* 不選擇當前物品 */ chooseGoods(goods_list, goods_num, goods_index + 1); /* 選擇當前物品 */ goods_list[goods_num] = goods_index; goods_num ++; chooseGoods(goods_list, goods_num, goods_index + 1); } } int main(){ int arr[5]; chooseGoods(arr, 0, 0); outputResult(); }
總結
對於暴力搜尋,最重要的是對於當前元素的選擇或者不選擇,另外對於語言來說,遞迴會生成函式呼叫棧,儲存當前的資料,不用多考慮陣列的引用問題。