poj 1742 多重背包问题 dp算法

Posted xuxiaojin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了poj 1742 多重背包问题 dp算法相关的知识,希望对你有一定的参考价值。

题意:硬币分别有 A1.....An种,每种各有C1......Cn个,问组成小于m的有多少种

思路:多重背包问题

     dp[i][j]表示用前i种硬币组成j最多剩下多少个  dp=-1的表示凑不齐

      dp[0][0]=0;

for(int i=0;i<n;i++)

    for(int j=0;j<=m;j++)

{    if(dp[i][j]>=0)   dp[i+1][j]=c[i];  //表示用前i种可以凑齐j元,自然就全部剩下了

      else if(j<a[i]||dp[i+1][j-a[i]]<=0) dp[i+1][j]=-1;  //表示没法凑

      else dp[i+1][j]=dp[i+1][j-a[i]]-1;   //表示用了i这种硬币

}

如何数组重用呢?

 dp[j]表示前i种硬币(循环)凑成j元最多剩下

dp[0]=0;

for(int i=0;i<n;i++)

for(int j=0;j<=m);j++)

{if(dp[j]>=0) dp[j]=c[i];

else if(j<a[i]||dp[j-a[i]]<=0) dp[j]=-1;

else dp[j]=dp[j-a[i]]-1;}

 

解决问题的代码:

#include <iostream>
#include <cstdio>
#include <string.h>
using namespace std;
int a[116];
int c[116];
int dp[100000 + 16];
int main()
{
        int n,m;
        while (scanf("%d%d", &n, &m) != EOF)
        {
               if (n == 0 && m == 0) break;
               for (int i = 0; i < n; i++)
                       scanf("%d", &a[i]);
               for (int i = 0; i < n; i++)
                       scanf("%d", &c[i]);
               memset(dp, -1, sizeof(dp));
               dp[0] = 0;
               for(int i=0;i<n;i++)
                       for (int j = 0; j <= m; j++)
                       {
                              if (dp[j] >= 0) dp[j] = c[i];
                              else if (j < a[i] || dp[j - a[i]] <= 0) dp[j] = -1;
                              else dp[j] = dp[j - a[i]] - 1;
                       }
               int ans = 0;
               for (int i = 1; i <= m; i++)
               {
                       if (dp[i] >= 0) ++ans;
               }
               printf("%d
", ans);
        }
        return 0;
}

 

以上是关于poj 1742 多重背包问题 dp算法的主要内容,如果未能解决你的问题,请参考以下文章

POJ 1742 Coins ( 经典多重部分和问题 && DP || 多重背包 )

poj1742 多重背包的可行性问题

POJ1742 Coins(男人八题之一)

POJ1742 Coins 多重背包+贪心

poj1742 Coins多重背包贪心

poj1742 Coins(多重背包+单调队列优化)