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; }
