Coins POJ 1742(多重背包)

原题

原题链接

题目大意

给出硬币面额及每种硬币的个数,求从1到m能凑出面额的个数。

题目分析

多重背包模板题,不过需要状压一波.首先定义dp[i][j]为前i个物品凑到j价格第i种硬币最多剩下多少.dp初始化为-1,点dp[0][0]=0,然后更新如下,if(dp[i-1][j]!=-1) dp[i][j]=c[i]

dp[i][j]=max(dp[i][j],dp[i][j-a[i]]).仔细观察dp更新方向可知,可以状压,把第一维去掉,然后把j的更新方向改为从小到大即可.

代码

 1 #include <cstdio>
 2 #include <cmath>
 3 #include <iostream>
 4 #include <cstring>
 5 #include <algorithm>
 6 #include <vector>
 7 #include <string>
 8 #include <utility>
 9 #include <queue>
10 #include <stack>
11 const int INF=0x3f3f3f3f;
12 using namespace std;
13 
14 
15 int dp[100001];
16 int v[101];
17 int c[101];
18 
19 int main()
20 {
21     int n,m;
22     while(cin>>n>>m&&(m||n))
23     {
24         for(int i=1;i<=n;i++) cin>>v[i];
25         for(int i=1;i<=n;i++) cin>>c[i];
26         memset(dp,-1,sizeof(dp));
27         dp[0]=0;
28         for(int i=1;i<=n;i++)
29         for(int j=0;j<=m;j++)
30         {
31             if(dp[j]>=0) dp[j]=c[i];
32             else if(j>=v[i]&&dp[j-v[i]]>0) dp[j]=dp[j-v[i]]-1;
33         }
34         int ans=0;
35         for(int i=1;i<=m;i++) if(dp[i]>=0) ans++;
36         cout<<ans<<endl;
37         memset(v,0,sizeof(v));
38         memset(c,0,sizeof(c));
39     }
40     return 0;
41 }

 

posted @ 2019-02-25 20:36  VBL  阅读(124)  评论(0编辑  收藏  举报