問題描述:
在節假日的時候,書店一般都會做**活動。由於《哈利波特》系列相當暢銷,店長決定通過**活動來回饋讀者。上櫃的《哈利波特》平裝本系列中,一共有五卷。假設每一捲單獨銷售均需8歐元。如果讀者一次購買不同的兩卷,就可以扣除5%的費用,三卷則更多。假設具體折扣的情況如下:
本數 折扣
2 5%
3 10% 4
20% 5
25%
在乙份訂單中,根據購買的卷數及本數,就會出現可以應用不同折扣規則的情況。但是,一本書只會應用乙個折扣規則。比如,讀者一共買了兩本卷一,一本卷二。那麼,可以享受到5%的折扣。另外一本卷一則不能享受折扣。如果有多種折扣,希望計算出的總額盡可能的低。
要求根據以上需求,設計出演算法,能夠計算出讀者所購買的一批書的最低**。
輸入樣例:
1 1 1 0 0
1 1 1 1 1
輸出樣例:
21.6 30
思路分析:
看到這個題目,任何人一開始想到的都是希望讓書本盡可能享受高折扣。但是隨著書本數目大於5本的時候,享受的總折扣就會相應出現了變化。
舉個例子, 當輸入的資料為(2,2,2,1,1)的時候,如果按照享受最高折扣計算,那麼對應的折扣策略就會拆分變成
(1,1,1,1,1)
和(1,1,1,0,0)
兩種,總**變為8
×0.75×5
+8×0.9×3
=51.6
歐元。但是如果我們變一下策略,選擇4+4,購買序列變為(1,1,1,1,0)
以及(1,1,1,0,1),那麼總共花費8
×0.8×5
+8×0.8×5
=51.2
歐元。
看到這裡,我們已經可以使用動態規劃通過計算總折扣數來計算最***格,當然,也可以採用優化的貪心演算法來實現,因為貪心演算法求解這類題目都是近似解,與最優解相近。
解題:
先將現有條件轉換一下(用百分比表示書本單價的多少倍):
本數 相對於書本單價的百分比 1
100% 2
190% 3
270% 4
320% 5
375%
具體說明一下吧:
當只有一本書的時候,沒有折扣,所以為100%,即原價8歐元購買;
當有兩本不同的書本,享有5%折扣,原本總價為200% ,減掉每本5%折扣,為190%,即15.2歐元;
當有三本不同的書本,享有10%折扣,原本總價為300%,減掉每本10%折扣,為270%,即21.6歐元;
當有四本不同的書本,享有20%折扣,原本總價為400%,減掉每本的20%折扣,為320%,即25.6歐元;
當有五本不同的書本,享有25%折扣,原本總價為500%,減掉每本的25%折扣,為375%,即30歐元;
以上折扣資料存放在mindis[6]中
即mindis[6] = ;
根據上述條件描述,我們可以定義出一條狀態轉移方程(核心):
f[y1,y2,y3,y4,y5] = min
其中必須保證y1>=y2>=y3>=y4>=y5,這樣才不會出現更多的冗餘資料。例如:(2,2,2,1,1)和(1,2,1,2,2)雖然不同,但是結果都是一樣的。
#define _crt_secure_no_warnings
#include #include #include using namespace std;
int main(void)
;//存放購買不同本數的折扣
int book[6] = ;
int bookcount = 0;//書本總類目
int bookprice = 8;//書本**
cout << "請輸入五類書中每一類書的數目:" << endl;
for (int i = 1; i <= 5; i++)
sort(book + 1, book + sizeof(book) / sizeof(int), greater());//保證y1>=y2>=y3>=y4>=y5
float arr[6][6][6][6][6] = ;//存放折扣計算過程
float mindis[6][6][6][6][6] = ;//存放享有的最大折扣
int y1 = 0;
int y2 = 0;
int y3 = 0;
int y4 = 0;
int y5 = 0;
/* 實現公式f(y1,y2,y3,y4,y5) = min 時間複雜度o(y1×y2×y3×y4×y5) 空間複雜度為(y1×y2×y3×y4×y5)
*/ for (y5 = 0; y5 <= book[5]; y5++)
;//存放不同購書策略所產生的臨時資料
int dir[5] = ;//存放下一步策略的y1 y2 y3 y4 y5
if (y5 > 0)
if (y4 > 0)
if (y3 > 0)
if (y2 > 0)
if (y1 > 0)
for (int i = 0; i < sizeof(a) / sizeof(double); i++)
arr[y1][y2][y3][y4][y5] = mindis[y1][y2][y3][y4][y5];//將mindis賦值給arr[y1][y2][y3][y4][y5],下一輪繼續使用}}
}} }
printf("當前購買書本可享有最低的**為:%.2f", mindis[book[1]][book[2]][book[3]][book[4]][book[5]]);//書本享有的總優惠*書本***書本數目/書本數目=書本享有總優惠*書本**
cout << endl;
system("pause");
return 0;
}
程式設計之美 買書問題 動態規劃
一,問題 上櫃的 哈利波特 平裝本系列,一共有五卷。假設每一捲單獨銷售均需8歐元。如果讀者一次購買不同的兩卷,就可以扣除5 的費用,三卷則更多。假設具體折扣的情況如下 本數2 折扣 5 本數3折扣 10 本數4折扣 20 本數 5 折扣25 問題 設計出演算法,能夠計算出讀者所購買的一批書的最低 二...
程式設計之美 買書問題
今天小夥伴在群裡給出了一道題 分享一道題,有興趣的可以做做哈。假設 冰與火之歌 有五卷,每一捲單獨買是20塊。兩卷連買減5 三卷連買減10 四卷連買減20 五卷連買減25 買相同的卷不打折。比如買兩本卷一,一本卷二,總 是58元。現買了一批書n,計算出它的最低 一看到這道題,瞬間就覺得這麼簡單有什麼...
《程式設計之美》之買書問題
這兩天剛看 程式設計之美 裡面的一些演算法有些確實經典,非常的感興趣,很喜歡自己先思考一下,然後看看書上的解析。對於1.4節的買書的問題,原書的解法二我看得不是很明白,而且解法一通過區域性最優解得到全域性最優解,這個肯定是不可取的,以下是我個人對這個問題的解法。本數 2 折扣 5 本數 3 折扣 1...