《程式設計之美》買書問題 動態規劃

2021-07-13 03:57:48 字數 2995 閱讀 3569

問題描述:

在節假日的時候,書店一般都會做**活動。由於《哈利波特》系列相當暢銷,店長決定通過**活動來回饋讀者。上櫃的《哈利波特》平裝本系列中,一共有五卷。假設每一捲單獨銷售均需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...