题目链接
http://acm.hdu.edu.cn/showproblem.php?pid=1786
题意
给出物品的数量n(1 < n < 10)和背包的容量m(0 < m < 1000000000),求使用最少的物品填满背包的情况,一定有解。每件物品的重量不超过100。
题解
首先,如果m超过100000的话,超过的部分用体积最大的物品尽量填满,然后剩下的部分使用完全背包求解。m不足100000的话,直接用完全背包求解即可。
为什么是100000:
物品最多为9件,每件物品最重不超过100,如果某一件物品使用超过100次的话,那么就可以用体积最大的那个物品代替一部分,因此剩下的容量应该为9x100x100,在这里取100000。
AC代码
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#define INF 1e8
using namespace std;
const int maxn = 100000;
const int maxv = 100110;
int dp[maxv];
int goods[20];
int main()
{
int n;long long int m;
while(~scanf("%d%lld",&n,&m)&&n&&m)
{
for(int i = 1; i < maxv; i++)dp[i] = INF;
for(int i = 0; i < n; i++)
{
scanf("%d", &goods[i]);
}
sort(goods,goods+n);
int ans = 0;
if(m > maxn)
{
long long int v = m - maxn;
ans += (v/goods[n-1]*3);
v = maxn + v - v/goods[n-1]*goods[n-1];
//cout << v << endl;
for(int i = 0; i < n; i++)
{
for(int j = goods[i]; j <= v; j++)
{
dp[j] = min(dp[j], dp[j-goods[i]] + 3);
}
}
//cout << dp[v] <<endl;
printf("%d\n", ans + dp[v]);
}
else
{
for(int i = 0; i < n; i++)
{
for(int j = goods[i]; j <= m; j++)
{
dp[j] = min(dp[j], dp[j-goods[i]] + 3);
}
}
printf("%d\n",dp[m]);
}
}
return 0;
}