題意:
有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 表示 上一次最多有多...