北大ACM 1742,Coins(多重揹包)

2021-09-22 05:40:02 字數 1400 閱讀 6880

多重揹包問題。

詳解見部落格:

這道題時間卡得超嚴,在看大佬的**之前瘋狂tle。

**如下:

#include#include#includeusing namespace std;

typedef long long ll;

const int maxn=1e5+5;

bool dp[maxn]; //用bool快超多

int a0[105];

int main()

if(c)

}} int sum=0;

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

sum+=dp[i];

printf("%d\n",sum);

} return 0;

}

其實後來一想,原題的題意理解錯了,題目是要求問1~m之間有多少可以構成多少種價值,而不是說構成價值1-m之間的方案數有多少種。(雖然最終結果都一樣)也因此,dp陣列可以用成bool型別。

事實上,這道題也屬於另外一種型別題,多重揹包可行性分析,對於這類問題,還有一種o(n*m)的演算法。

強推:狀態:dp[i,j]表示用前i中物品構成價值j時,第i種硬幣最多剩下多少種。

如果能夠構成價值j,則0<=do[i,j]<=c[i],否則dp[i,j]=-1.

對於這個演算法,每一步都要進行初始化:

if(d[i-1,j]>=0) dp[i,j]=c[i]

else dp[i,j]=-1;

狀態轉移方程:

for(j=0,j<=m-a[i],;j++)

if(dp[i,j]>0)

dp[i,j+a[i]]=max(dp[i,j+a[i]],dp[i,j]-1);

這些會在**中解釋。

**如下:

#include#include#includeusing namespace std;

typedef long long ll;

const int maxn=1e5+5;

int dp[maxn]; //這裡要用成一維陣列,否則會爆記憶體(poj這道題卡得真的是嚴)

int a0[105];

int main()

int sum=0;

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

if(dp[i]>=0) //價值為j的方案存在

sum++;

printf("%d\n",sum);

} return 0;

}

個人覺得,這種演算法乙個核心就是用前面已經能夠構成的價值方案,去推出更多的價值。

poj 1742 Coins 多重揹包

題意很簡單,有n種硬幣,每種硬幣面額多大,有多少個,求可以構成m以內的面額有多少種。開始用的是普通的多重揹包的求法,裸裸的超時了,看了別人的 發現可以優化很多。用usea這個來儲存用來多少個a硬幣,避免的很多無用的計算。先貼以前超時的 include include int dp 100005 in...

POJ 1742 Coins 多重揹包DP

題意 有n種面額的硬幣。面額 個數分別為a i c i,求最多能搭配出幾種不超過m的金額?思路 dp j 就是總數為j的價值是否已經有了這種方法,如果現在沒有,那麼我們就乙個個硬幣去嘗試直到有,這種價值方法有了的話,那麼就是總方法數加1。多重揹包可行性問題 傳統多重揹包三重迴圈會超時,因為只考慮是否...

poj1742 Coins 多重揹包優化DP

給定n個物品,第i個物品價值為a i 數量為c i 求可以組成的小於m的價值的個數。好像n,m的範圍比較大,暴力跑二進位制優化的多重揹包是可以卡過去的。但是有一種o nm o n m 的方法來優化多重揹包,即在列舉體積的時候我們按照完全揹包來順序列舉,完全揹包裡的列舉體積是可以滿足重複選擇同意物品的...