一个背包算法的源代码

在工作中遇到一个奇怪的要求,给定空间和时间,要求将特定设备的配置最佳化,这就用到了“背包”算法,很有趣,我写了一个比较通用的算法(原理就是穷举),下面是源代码:

#include <vector> #include <cassert> #include <cmath> #include <iostream> template <typename _W, typename _V> class Choice { public: _W weight; _V value; Choice(_W _weight, _V _value) : weight(_weight) , value(_value) { } }; template <typename _W, typename _V> class Item : public std::vector< Choice<_W, _V> > { }; template <typename _W, typename _V> class ItemList : public std::vector< Item<_W, _V> > { }; class ItemChoiceIndexList : public std::vector<size_t> { }; template <typename _W, typename _V> bool CalculateBestItemChoiceList(_W capacity, typename ItemList<_W, _V>::const_iterator item_begin, typename ItemList<_W, _V>::const_iterator item_end, ItemChoiceIndexList & retItemChoiceList, _W & retTotalWeight, _V & retTotalValue) { assert(retItemChoiceList.empty()); // 深度检测 if(item_begin == item_end) { retTotalWeight = 0; retTotalValue = 0; return true; } bool findMinChoiceList = false; _V maxTotalValue = 0; for(size_t choice_i = 0; choice_i < item_begin->size(); choice_i++) { const Choice<_W, _V> & choice = (*item_begin)[choice_i]; assert(choice.value > 0); // 如果当前选项大于总空间,本次组合不可选 if(choice.weight > capacity) { continue; } // 获取剩下总空间的最佳背包组合 ItemChoiceIndexList retRemainingItemChoiceList; _W retRemainingTotalWeight; _V retRemainingTotalValue; if(!CalculateBestItemChoiceList( capacity - choice.weight, item_begin + 1, item_end, retRemainingItemChoiceList, retRemainingTotalWeight, retRemainingTotalValue)) { continue; } // 如果这次的组合获得的剩余空间最小,这保存这次的组合 if(retRemainingTotalValue + choice.value > maxTotalValue) { findMinChoiceList = true; maxTotalValue = retRemainingTotalValue + choice.value; retItemChoiceList.clear(); retItemChoiceList.push_back(choice_i); retItemChoiceList.insert( retItemChoiceList.end(), retRemainingItemChoiceList.begin(), retRemainingItemChoiceList.end()); retTotalValue = maxTotalValue; retTotalWeight = retRemainingTotalWeight + choice.weight; } } // 没有找到合适的组合 if(!findMinChoiceList) { return false; } assert(!retItemChoiceList.empty()); return true; } int main(int argc, char ** argv) { typedef unsigned int WeightType; typedef float ValueType; // 初始化ItemList用以测试 ItemList<WeightType, ValueType> itemList; const int item_count = 9; const int choice_count = 3; for(int i = 0; i < item_count; i++) { Item<WeightType, ValueType> item; for(int w = 1; w < 2 * choice_count; w += 2) { item.push_back(Choice<WeightType, ValueType>(w, sqrt((float)w))); } itemList.push_back(item); } // 设置总空间 const WeightType capacity = 35; // 测试,并获得最小剩余空间 ItemChoiceIndexList itemChoiceList; WeightType totalWeight; ValueType totalValue; if(!CalculateBestItemChoiceList( capacity, itemList.begin(), itemList.end(), itemChoiceList, totalWeight, totalValue)) { std::cout << "cannot calculate best item choice list" << std::endl; } else { std::cout << "the best choice list: total = " << capacity << ", remaining = " << capacity - totalWeight << std::endl; for(size_t i = 0; i < itemList.size(); i++) { std::cout << "item [" << i << "]:"; Item<WeightType, ValueType>::const_iterator choice_iter = itemList[i].begin(); for(; choice_iter != itemList[i].end(); choice_iter++) { std::cout << " (" << choice_iter->weight << ", " << choice_iter->value << ")"; } std::cout << " choice: " << itemChoiceList[i] + 1 << std::endl; } } return 0; }

你可能感兴趣的:(算法,list,vector,测试,iterator,float)