POJ1787 完全揹包 物品計數 路徑輸出

2021-07-16 14:12:26 字數 1661 閱讀 4052

題意:

有1,5,10,25四種硬幣,給每種硬幣的數量和要組合成的價值,求剛好達到價值時用的硬幣最多,然後還要輸出具體的用的數量

前言:

一開始是偶然看見了kuangbin爺的題解說是完全揹包+路徑,很好奇啊。

思路(kuangbin爺** orz):

乙個完全揹包,加個計數,加個路徑。

因為題目要求是求乙個max硬幣數量,所以直觀上我們感覺就是面值小的硬幣用的越多越好,然後在dp更新的時候,基於小面值使用大面值。所以val陣列是從小到大,目的是盡可能使用更多的小面值硬幣達到dp陣列是每次都是最多的。然而如果是求最小硬幣數,直接就可以把面值陣列掉一下頭就好啦~

突然有個問題(太弱就會瞎想):

有沒有存在可能被給出的p面值沒有被更新到,雖然dp陣列判斷條件是判斷誰大,所以初始化0就好了(p>=1),一旦符合就是有符合的條件。所以是成立。

忽略以上的問題,利用完全揹包的思想:

首先在更新的時候必須保證dp[j-val[i]]>=0的,第一枚硬幣的更新是以 j-val[i] = 0為基礎開始的,以至於dp陣列才可以代表的是 j 面值的最大硬幣數。所以初始化dp是負數。

然後加乙個cnt,非常nice的乙個想法。

具體寫法:

①:我們可以開乙個num陣列去記錄某價值下的某硬幣的使用情況。

②:我們可以開個pre陣列去記錄一下某 j 面值的前面的j-val[i],然後遞迴到0,中間的差值就是被使用價值的硬幣,再開乙個陣列記錄一下就好了。

除了這個方法,還有多重揹包+路徑;

貼一發挫code……….

#include

#include

#include

#include

#include

using

namespace

std;

#define eps 1e-8

typedef __int64 ll;

const

int n=1e4+10;

int val[4]=;

int dp[n]; //在該面值的最大硬幣數量

int num[5];

int pre[n];//記錄揹包路徑

int cnt[n];//每次更新是臨時計數

int ans[30]; //計數

int main()

if(!t&&!num[0]&&!num[1]&&!num[2]&&!num[3]) break;//在這裡wa了,以後判0乖乖這樣做。

memset(pre,0,sizeof(pre));

memset(dp,-1,sizeof(dp));

dp[0]=0;

pre[0]=-1;

for(int i=0;i<4;i++)}}

if(dp[t]<0)

//printf("%d\n",dp[t]);

memset(ans,0,sizeof(ans));

int x=t;

while(1)

printf("throw in %d cents, %d nickels, %d dimes, and %d quarters.\n",ans[1],ans[5],ans[10],ans[25]);

}return

0;}

POJ 1787 完全揹包,記錄路徑

題意 你有1,5,10,25四種硬幣數量有限,你想買 為p的咖啡,問你能不能購買,要求花的硬幣盡量多,並且輸出每種硬幣花了多少 思路 看起來像多重揹包加記錄路徑但用完全揹包比較好寫 include include include include include include include inc...

poj1787 完全揹包 路徑記錄總結

第一次接觸完全揹包,看了別人思路後再寫的。關於本題的揹包問題的幾個總結 1.注意分析全面轉移條件,有時候這個問題會卡住 2.這題的揹包是每個物品有限個,本題中用cnt在轉移條件中限制 3.學會將問題轉化,例如本題一開始想不到用揹包,考慮用搜尋如果真的搜尋的話效率一定低下,但要求是硬幣數最多的組合,就...

poj 1787 多重揹包(硬幣付款不找錢)

題意 分硬幣,有1,5,10,25四種硬幣,給定每種硬幣的數量,給定要組合成的價值,問剛好達到價值時用的硬幣最多的情況。思路 dp j 表示 j 塊錢最多由多少塊硬幣組成,used j 表示 j 塊錢時,已經放了多少同種類的硬幣。實際上path用一維陣列即可,使得 path j 表示 上一次最多有多...