#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
using namespace std;
int dp[25000]; //dp[i] 表示组成i元钱用的钱的最少张数;(用多重背包求得);
int dp1[25000]; //dp1[i] 表示组成i元钱用的最少钱数 (用的是找回的钱组成 用完全背包求得);
int c[105], v[105];
int n, T;
void zeroOnepake(int v, int k) {
for(int i = 20004; i >= v; i--) {
dp[i] = min(dp[i], dp[i-v]+k);//dp[i] i 大小的空间一定是被占满,然后,得到的对应的价值;
//背包的核心是用在空间一定是,尽可能大的获得我们想要的东西;
//对于min(dp[i], dp[i - v] + k) 能组成i元钱所用的最少钱的个数,
}
}
void work(int v, int m) { //多重背包求解代码段;
int t = 1;
while(t < m) {
zeroOnepake(v*t, t);
m-= t;
t*= 2;
}
zeroOnepake(v*m, m); //不要忘记这一步;
}
void work1(int v) {
for(int i = v; i < 20005; i++) { //完全背包代码段;
dp1[i] = min(dp1[i], dp1[i-v]+1);
}
}
void init() {
for(int i = 0; i < n; i++) {
scanf("%d", &v[i]);
}
for(int i = 0; i < n; i++) {
scanf("%d", &c[i]);
}
for(int i = 0; i < 20005; i++) {
dp[i] = 999999;
dp1[i] = 999999;
}
dp[0] = 0;
dp1[0] = 0;
for(int i = 0; i < n; i++) {
work(v[i], c[i]);
}
for(int i = 0; i < n; i++) {
work1(v[i]);
}
}
int main()
{
int q = 1;
while(scanf("%d%d", &n, &T) != EOF) {
if(n == 0 && T == 0)
break;
init();
int ans = 999999;
for(int i = T; i <= 20000; i++) {
ans = min(ans, dp[i] + dp1[i-T]); //ans 表示i元钱所用钱的张数;
}
if(ans == 999999)
ans = -1;
printf("Case %d: %d\n", q++, ans);
}
return 0;
}
hdu3591The trouble of Xiaoqian(多重背包)
最新推荐文章于 2018-03-28 17:43:00 发布