【问题描述】
问题1:装满背包
给出 N 个物品,第 i 个物品的体积为 v[i],价值为 p[i],现在需要选择一些物品装满容量为 C 的背包,所能获得的最大价值,如果不能装满,则输出-1。
问题2:K背包
给出 N 个物品,第i个物品的体积为 v[i],价值为 p[i],现在需要选择 K 个装入容量为 C 的背包,所能获得的最大价值,如果无解,则输出-1。
【输入格式】
第 1 行:两个整数 C 和 N 。
接下来的N行:每行两个整数,表示 v[i] 和 p[i] 。
最后一行,一个整数 K (针对问题2)。
【输出格式】
第 1 行:一个整数,表示问题1的解,不能装满,则输出-1。
第 2 行:一个整数,表示问题2的解,如果无解,则输出-1。
【输入样例】
【样例1】
10 5
2 2
8 7
3 3
5 4
7 8
3
【样例2】
10 5
2 2
8 7
3 3
5 4
7 8
4
【样例3】
16 5
3 3
1 3
2 1
5 4
4 6
3
【输出样例】
【样例1】
11
9
【样例2】
11
-1
【样例3】
-1
13
【数据范围】
1<=K<=N<=100
1<=v[i]<=C<=20000
问题1:装满背包
给出 N 个物品,第 i 个物品的体积为 v[i],价值为 p[i],现在需要选择一些物品装满容量为 C 的背包,所能获得的最大价值,如果不能装满,则输出-1。
问题2:K背包
给出 N 个物品,第i个物品的体积为 v[i],价值为 p[i],现在需要选择 K 个装入容量为 C 的背包,所能获得的最大价值,如果无解,则输出-1。
【输入格式】
第 1 行:两个整数 C 和 N 。
接下来的N行:每行两个整数,表示 v[i] 和 p[i] 。
最后一行,一个整数 K (针对问题2)。
【输出格式】
第 1 行:一个整数,表示问题1的解,不能装满,则输出-1。
第 2 行:一个整数,表示问题2的解,如果无解,则输出-1。
【输入样例】
【样例1】
10 5
2 2
8 7
3 3
5 4
7 8
3
【样例2】
10 5
2 2
8 7
3 3
5 4
7 8
4
【样例3】
16 5
3 3
1 3
2 1
5 4
4 6
3
【输出样例】
【样例1】
11
9
【样例2】
11
-1
【样例3】
-1
13
【数据范围】
1<=K<=N<=100
1<=v[i]<=C<=20000
1<=p[i]<=1,000,000
【分析】
和普通的0-1背包不太一样
问题一:
状态方程:f(i,j)表示前i个背包选物品刚好放满j容量的背包所能获得的最大价值
状态转移:f(i,j)=max{ f(i-1,j) , f( i-1,j-v[i] )+p[i] }
边界(重点):f(0,0)=0 f(0,j)=-oo (-oo表示不可行)
问题二:
f(i,j,k) 表示前i个背包中选j个体积不超过k所能获得的最大价值
f(i,j,k)=max:f(i-1,j,k),f(i-1,j-1,k-v[i])+p[i]
边界:f(i,0,k)=0
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,c,k,v[105],p[105];
int ans[20003],a[102][20003];
int main()
{
//第一问
memset(ans,0xaf,sizeof(ans));//初始化-oo
ans[0]=0;
scanf("%d%d",&c,&n);
for(int i=1;i<=n;i++) scanf("%d%d",&v[i],&p[i]);
scanf("%d",&k);
for(int i=1;i<=n;i++)
{
for(int j=c;j>=v[i];j--)
{
ans[j]=max(ans[j],ans[j-v[i]]+p[i]);
}
}
if(ans[c]>=0) printf("%d\n",ans[c]);
else printf("-1\n");
/*
对递推方程的分析:
f(i,j,k) 表示前i个背包中选j个体积不超过k所能获得的最大价值
f(i,j,k)=max:f(i-1,j,k),f(i-1,j-1,k-v[i])+p[i]
边界:f(i,0,k)=0
*/
memset(a,0xaf,sizeof(a));
for(int i=0;i<=20000;i++) a[0][i]=0;
for(int i=1;i<=n;i++)
{
for(int j=k;j>=1;j--)
{
for(int q=c;q>=v[i];q--)
a[j][q]=max(a[j][q],a[j-1][q-v[i]]+p[i]);
}
}
if(a[k][c]>=0) printf("%d\n",a[k][c]);
else printf("-1\n");
return 0;
}