http://poj.org/gotoproblem?pid=3260

(1)多重背包的处理方式:转化为分组背包(1,2,4,8,余数)。具体细节参见代码:

scanf("%d", &num[i]);
tn=num[i];
while(tn>0)
{
    if(tn<x) {map[i][tot++]=tn;break;}
    map[i][tot++]=x;
    tn-=x; x*=2;
}

(2)接下来是装多重背包,注意细节  for(j=0;map[i][j];j++) 

           而不是      for(j=1;map[i][j];j++)

    进而用万群被白调整,注意循环顺序:for(k=V-mon[i];k>=0;k--)

               而不是 for(k=0;k<=V-mon[i];k++)

(3)悬而未解之问:取上限为V=10000就AC了,不合常理,应该是数据问题吧。。。

  有待解决。

具体代码:

View Code
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int N=11000;
const int Inf=1<<29;
int n, m, V;
int mon[120], num[120];
int map[120][20];
int dp[N];
int main()
{
    int i, j, k;
    while(scanf("%d%d", &n, &m)!=EOF)
    {
        for(i=1;i<=n;i++) scanf("%d", &mon[i]);
        memset(map, 0, sizeof(map));
        for(i=1;i<=n;i++)
        {
            int x=1, tot=0, tn;
            scanf("%d", &num[i]);
            tn=num[i];
            while(tn>0)
            {
                if(tn<x) {map[i][tot++]=tn;break;}
                map[i][tot++]=x;
                tn-=x; x*=2;
            }
        }
        V=10000;
        for(i=0;i<=V;i++) dp[i]=Inf;
        dp[0]=0;
        for(i=1;i<=n;i++)
            for(j=0;map[i][j];j++)
                for(k=V;k>=map[i][j]*mon[i];k--)
                    dp[k]=min(dp[k], dp[k-map[i][j]*mon[i]]+map[i][j]);
        for(i=1;i<=n;i++)
            for(k=V-mon[i];k>=0;k--)
                dp[k]=min(dp[k], dp[k+mon[i]]+1);
        if(dp[m]==Inf)  printf("-1\n");
        else printf("%d\n", dp[m]);
    }
    return 0;
}