因为某位同学最近在学背包,还老是问我问题,然后我就被拉去一起写背包问题了,不过也好,把以前的不会写的恰好装满的背包问题给写了。
其实还是挺好的。。。下面来说一说吧:
首先,你要把普通的背包熟悉(高深的我也不会了),然后如果是求最小值的恰好装满背包,那就先 int INF = 1000000; 然后全部的初始化为 - INF,dp[1] = 0; 这样就可以了,类似的,当求最大值的恰好装满背包,那就全部初始化为INF 即可。
题目号 TOJ 3232 TOJ 礼品兑换 杭电 HDU 1114 Piggy-Bank
下面来两道例题吧
http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=3232
这题是典型的多重背包,取最大值
#include<stdio.h>
#include<string.h>
const int N = 110;
const int INF = 10000000; // 尽量定义的大一点,具体多大,我也不知道,应该这么大就可以了吧
int dp[100010];
int c[N], v[N];
int max(int x, int y)
{
return x > y ? x : y;
}
int main()
{
int n;
int x, y, i, j;
while(~scanf("%d",&n))
{
while(n--)
{
scanf("%d%d",&x,&y);
int price, weight, sum;
int cnt= 1;
for (i = 1; i <= y; i ++) // 用二进制的多重背包的方法
{
scanf("%d%d%d",&price, &sum, &weight);
int t = 1;
while(sum >= t)
{
c[cnt] = t * price;
v[cnt++] = t * weight;
sum =sum - t;
t = t << 1;
}
if(sum)
{
c[cnt] = sum * price;
v[cnt++] = sum * weight;
}
}
for(i = 0; i <= x; i ++)
dp[i] = - INF; // 初始化要注意
dp[0] = 0;
for (i = 1 ; i < cnt ; i ++ )
{
for(j = x; j >= v[i]; j --)
dp[j] = max(dp[j], dp[j - v[i]] + c[i]);
}
if(dp[x] < 0)
printf("This is impossible.\n");
else
printf("The maximum value is %d.\n",dp[x]);
}
}
return 0;
}
这题是杭电的01 - 背包 , 是取最小值的
http://acm.hdu.edu.cn/showproblem.php?pid=1114
#include <stdio.h>
const int N = 550;
int c[N];
int w[N];
int dp[10010];
const int INF = 10000000;
int min(int x, int y)
{
return x < y ? x : y ;
}
int main()
{
int n, m;
int i, j;
int a, b;
int cc, ww;
while(~scanf("%d",&n))
{
while(n --)
{
scanf("%d%d", &cc, &ww);
scanf("%d", &m);
for(i = 0; i <= ww - cc; i ++)
dp[i] = INF;
for(i = 0; i < m; i ++)
scanf("%d%d",&c[i], &w[i]);
dp[0] = 0;
for(i = 0;i < m; i ++)
{
for(j = w[i]; j <= ww - cc; j ++)
dp[j] = min(dp[j - w[i]] + c[i], dp[j]);
}
if(dp[ww - cc] == INF)
printf("This is impossible.\n");
else
printf("The minimum amount of money in the piggy-bank is %d.\n",dp[ww - cc]);
}
}
return 0;
}