[问题描述]
在一条街上有n个商店,每个商店有一种商品可卖,有数字代替商品名,商品都有价格,各个商店可卖同一种商品而价格可以不一样,现在又一个人要从街头走到结尾去购物,他手上有一张要购买的商品的清单,现在必须按照清单上的次序依次购买商品( 或者可以不按照清单顺序购买 ) ,求花费最小的购物方法;
例如 购物清单:(数字代替商品名) 2 2 5 1
商店情况:
商店 S1 S2 S3 S4 S5 S6 S7 S8
商品 2 3 2 5 2 5 4 1
价格 50 80 40 60 42 65 100 30
[不按照清单顺序-贪心算法] 花费最小的方法是:S3 S4 S5 S8 === 40+60+42+30=172(一个商店最多购买同类商品一个)
[按照清单的顺序-动态规划] 花费最小的方法是:S3 S5 S6 S8 === 40+42+65+30=177(一个商店最多购买同类商品一个)
[问题解决]
不按照清单数序-得出最省钱的最优解:
Step1:利用一个数组Store[8] ,存放商店的下标,1...8,,然后根据这样的排序比较规则对该数组的数组下标进行排序
(1)按照商品编号小的在前,大的在后
(2)同样的商品编号,价格小的在前,价格大的在后
然后对购物清单的各物品的商品编号进行进行排序,小的在前,大的在后
Step2:然后然后同时遍历排序后的 “购物清单数组” 和 “Store数组”,查看是否当前需要购买的商品即使该Store[i]商店出售的商品,是则输出该商店名称,并累加该商品价格。
按照清单顺序-按清单顺序最省的解答:
在找到一种可能的情况下,抛开找到的第一个匹配的商店,如果在该商店后续的商店中还存在匹配的情况,且花费更小,则得出较省的解答,如果后续商店中不存在匹配的情况,则后续的后续不可能再出现匹配的情况,直接退出匹配,当前得出的花费最省的情况即为解答。
[程序如下]
/* * main.cpp * * Created on: 2009-7-4 * Author: NeeSky */ #define MAXSIZE 100 #include <iostream> using namespace std; int GoodsID[MAXSIZE]; /*Goods ID of Store i*/ int GoodsPrice[MAXSIZE]; /*Goods Price*/ int OrderList[MAXSIZE]; /*Order-List for Goods */ /*** * Initialize the Problem and Global Variables and Output the Original Problem */ void InitPurchaseProblem(const int goodsID[], const int goodsPrice[], const int numStore, int orderList[], const int numNeed ) { for (int i = 0; i < numStore; ++i) { GoodsID[i] = goodsID[i]; GoodsPrice[i] = goodsPrice[i]; if (i < numNeed)OrderList[i] = orderList[i]; } for (int i = 0; i < numStore; ++i)cout << "S[" << i + 1 << "] ";cout << endl; for (int i = 0; i < numStore; ++i)cout << GoodsID[i] << " ";cout << endl; for (int i = 0; i < numStore; ++i)cout << GoodsPrice[i] << " ";cout << endl << endl; cout << "Order List : "; for (int i = 0; i < numNeed; ++i)cout << OrderList[i] << " ";cout << endl << endl; return; } /*** * Be used to output the result of purchase plan */ void outputPlan_forPurchase(int StorePurchased[], int numNeed ) { int SumPrice = 0; for (int j = 0; j < numNeed; j++) { if (StorePurchased[j] != -1) { if (j != 0) cout << " + "; SumPrice = SumPrice + GoodsPrice[StorePurchased[j]]; cout << "S[" << StorePurchased[j] + 1 << "]"; } else break; } cout << " = " << SumPrice << endl; return; } /*** * [ Important ] The Compare Principare */ int StoreCompare(const void* arg1, const void* arg2 ) { int* storeA = (int*) arg1; int *storeB = (int*) arg2; if (GoodsID[*storeA] > GoodsID[*storeB]) return 1; if (GoodsID[*storeA] < GoodsID[*storeB]) return -1; if (GoodsID[*storeA] == GoodsID[*storeB] && GoodsPrice[*storeA] > GoodsPrice[*storeB]) return 1; if (GoodsID[*storeA] == GoodsID[*storeB] && GoodsPrice[*storeA] == GoodsPrice[*storeB]) return 0; return -1; } /*** * Make the Purchase Plan */ void MakePlan_forPurchase(int numStore, int OrderList[], int numNeed, bool asOrderList ) { int StorePurchased[numNeed];//Store ID for Purchased for (int i = 0; i < numNeed; ++i)StorePurchased[i] = -1; //Initialize the Purchased Store ID to be -1 int StoresID[numStore];//Store ID for (int i = 0; i < numStore; ++i)StoresID[i] = i;//Initialize Store ID if (asOrderList == false) /********Greed Algorithm***************/ { std::sort(OrderList, OrderList + numNeed);//Make it be order as GoodsID std::qsort(StoresID, numStore, sizeof(int), StoreCompare);//Make it be order as "StoreCompare" Function* for (int i = 0 , j = 0; i < numStore && j < numNeed; ++i)//Start Purchase Goods if (GoodsID[StoresID[i]] == OrderList[j]) StorePurchased[j++] = StoresID[i]; std::sort(StorePurchased, StorePurchased + numNeed); } else /*****************Dynamic Plan******************/ { int MinMoney=0; for(int i=0; i<numStore; ) { int StorePurchasedNow[numNeed]; int MinMoneyNow=0;int k=0; for(int j= i; j < numStore && k<numNeed; ++j) { if(GoodsID[j]==OrderList[k]) { StorePurchasedNow[k++]= j; MinMoneyNow+=GoodsPrice[j]; } } if(k==numNeed&& (MinMoneyNow < MinMoney || MinMoney==0)) { MinMoney = MinMoneyNow; for(int t=0; t<numNeed; ++t) StorePurchased[t] = StorePurchasedNow[t]; i=StorePurchased[0]+1; //The Next Possible }else break; } } outputPlan_forPurchase(StorePurchased, numNeed); return; } int main() { const int numStore = 9; const int goodsID[numStore] = { 2, 5, 2, 1, 2, 2, 5, 5,1 }; //Goods ID of Store i const int goodsPrice[numStore] = { 30, 10, 25, 5, 20, 40, 15, 30, 10 };//Goods Price // const int numStore = 8; // const int goodsID[numStore] = { 2, 3, 2, 5, 2, 5, 4, 1 }; //Goods ID of Store i // const int goodsPrice[numStore] = { 50, 80, 40, 60, 42, 65, 100, 30 };//Goods Price const int numNeed = 4; int orderList[numNeed] = { 2, 2, 5, 1 }; InitPurchaseProblem(goodsID, goodsPrice, numStore, orderList, numNeed);// Initilize the Array cout<<"Dynamic Plan for purchase as Order List Sequency: "<<endl; MakePlan_forPurchase(numStore, OrderList, 4, true); cout<<endl; cout<<"Greed Algorithm for purchase [not]as Order List Sequency: "<<endl; MakePlan_forPurchase(numStore, OrderList, 4, false); return 0; }
[输出]:
S[1] S[2] S[3] S[4] S[5] S[6] S[7] S[8]
2 3 2 5 2 5 4 1
50 80 40 60 42 65 100 30
Order List : 2 2 5 1
Dynamic Plan for purchase as Order List Sequency:
S[3] + S[5] + S[6] + S[8] = 177
Greed Algorithm for purchase [not]as Order List Sequency:
S[3] + S[4] + S[5] + S[8] = 172
S[1] S[2] S[3] S[4] S[5] S[6] S[7] S[8] S[9]
2 5 2 1 2 2 5 5 1
30 10 25 5 20 40 15 30 10
Order List : 2 2 5 1
Dynamic Plan for purchase as Order List Sequency:
S[3] + S[5] + S[7] + S[9] = 70
Greed Algorithm for purchase [not]as Order List Sequency:
S[2] + S[3] + S[4] + S[5] = 60