多重揹包問題。
詳解見部落格:
這道題時間卡得超嚴,在看大佬的**之前瘋狂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 的方法來優化多重揹包,即在列舉體積的時候我們按照完全揹包來順序列舉,完全揹包裡的列舉體積是可以滿足重複選擇同意物品的...