題目1025 最大報銷額 01揹包問題

2021-07-23 19:13:42 字數 2719 閱讀 7499

題目描述:現有一筆經費可以報銷一定額度的發票。允許報銷的發票型別包括買圖書(a類)、文具(b類)、差旅(c類),要求每張發票的總額不得超過1000元,每張發票上,單項物品的價值不得超過600元。現請你編寫程式,在給出的一堆發票中找出可以報銷的、不超過給定額度的最大報銷額。

輸入:測試輸入包含若干測試用例。每個測試用例的第1行包含兩個正數 q 和 n,其中 q 是給定的報銷額度,n(n<=30)是發票張數。隨後是 n 行輸入,每行的格式為:

m type_1:price_1 type_2:price_2 ... type_m:price_m

其中正整數 m 是這張發票上所開物品的件數,type_i 和 price_i 是第 i 項物品的種類和價值。物品種類用乙個大寫英文本母表示。當n為0時,全部輸入結束,相應的結果不要輸出。

輸出:對每個測試用例輸出1行,即可以報銷的最大數額,精確到小數點後2位。

樣例輸入:

200.00 3

2 a:23.50 b:100.00

1 c:650.00

3 a:59.99 a:120.00 x:10.00

1200.00 2

2 b:600.00 a:400.00

1 c:200.50

1200.50 3

2 b:600.00 a:400.00

1 c:200.50

1 a:100.00

100.00 0

樣例輸出:

123.50

1000.00

1200.50

筆記:這個題目考察的是01揹包問題,用到的演算法思想是動態規劃。我在得出能夠報銷的發票陣列後,我剛開始想到的是用貪心,後來發現,此類非連續性的問題不能用貪心。比如最大報銷額是1000,發票的金額為600、500、500。用貪心的思路:先報銷最大的600,再在剩下的發條中繼續找能夠報銷的最大的,由於一張發票只能選擇報或不報,所以得出最大報銷額為600,其實這是錯誤的。選擇500 + 500的方法可以獲得1000的報銷額,而對於這種非連續形的求最大價值的問題,就需要動態規劃來解題了。

01揹包問題:乙個揹包總容量為v,現在有n個物品,第i個物品體積為w(i),價值為v(i),現在往揹包裡面裝東西,怎麼裝能使揹包的內物品價值最大?

關於這種問題用動態規劃有乙個解題的關鍵思路:

f[i][j] = max

f[i][j]表示揹包容量為j時放入i件物品的最大價值,這個最大價值為:

max

方便理解,自己敲了一遍如下**:

#includeusing namespace std;  

#define v 1500

unsigned int f[10][v];//全域性變數,自動初始化為0

unsigned int weight[10];

unsigned int value[10];

#define max(x,y) (x)>(y)?(x):(y)

int main()

for (int i=1; i<=n; i++)

for (int j=1; j<=m; j++)

else

f[i][j]=f[i-1][j];

} cout<

這個公式去計算最大價值的時候會占用很大的記憶體空間,因為在計算發f[i][j]時只用到了f[i-1][0......j]的資料,即計算第i行(加入第i個物品時)只用i-1行的資料,因此這個二維資料只需要用一維陣列表示就行,進一步得出下面的公式:

f[j] = max

上面的**就改下了下面這樣:

#includeusing namespace std;

#define v 1500

unsigned int f[v];//全域性變數,自動初始化為0

unsigned int weight[10];

unsigned int value[10];

#define max(x,y) (x)>(y)?(x):(y)

int main()

for (int i=1; i<=n; i++)

for (int j=m; j>=1; j--)

} cout<

我的ac**:

#include#include#includeusing namespace std;

int f[3001000];

int max(int a,int b)

int main()

else if(type == 'b')

else if(type == 'c')

else

if(a + b + c > 100000 || a > 60000 || b > 60000 || c > 60000)

}if(flag)

} for(i = 1;i < t; i++)

}printf("%.2lf\n",f[q]/100.00);

} return 0;

}

注:這個題目因為最大價值(最大報銷額)為實型,因為用動態規劃時,陣列裡要求為int型, 題目要求精確到小數點後2位,所以,我們可以將所有金額乘以100,將所有金額轉為int型,最後得出的結果再除以100.00即可。

如果你看不懂可以去看這個部落格:    

最大報銷額(01揹包)

紀念一下這個題,讀題很重要,單項物品價值不的超過600元,就是說如果一張報銷單同時含幾個型別相同的,這幾個和不超過 600元,否則不報銷,被卡到這了 剩餘就按01揹包做啦 現有一筆經費可以報銷一定額度的發票。允許報銷的發票型別包括買圖書 a類 文具 b類 差旅 c類 要求每張發票的總額不得超過100...

1025 最大報銷額

題目描述 現有一筆經費可以報銷一定額度的發票。允許報銷的發票型別包括買圖書 a類 文具 b類 差旅 c類 要求每張發票的總額不得超過1000元,每張發票上,單項物品的價值不得超過600元。現請你編寫程式,在給出的一堆發票中找出可以報銷的 不超過給定額度的最大報銷額。輸入 測試輸入包含若干測試用例。每...

1025 最大報銷額

1025 最大報銷額.cpp 定義控制台應用程式的入口點。題目1025 最大報銷額 時間限制 1 秒記憶體限制 32 兆特殊判題 否提交 4936解決 1184 題目描述 現有一筆經費可以報銷一定額度的發票。允許報銷的發票型別包括買圖書 a類 文具 b類 差旅 c類 要求每張發票的總額不得超過100...