题解 GDFZOJ 【646】 01背包
GDFZOJ原题地址戳这儿
洛谷原模板题戳这儿
这是一道
一、审题
有N件物品和一个容量为
数据范围:
似乎并没有什么关键点,粗略判断时间复杂度,
二、做题
0、贪心
| 若果你还没学过 |
物品编号 | A | B | C |
|---|---|---|---|---|
| C | 6 | 5 | 5 | |
| W | 9 | 6 | 6 | |
| Sum | 1.5 | 1.2 | 1.2 |
根据以上的贪心策略,我们应该是要选
1、背包
既然确定了是动规,那就可以愉快地开始推式子啦
让我假设现在的背包的容量C=10;
| 物品编号 | 物品重量 | 物品价值 |
|---|---|---|
| 1 | 5 | 20 |
| 2 | 6 | 10 |
| 3 | 4 | 12 |
我们用
那考虑一下当前容量
接着 i=2i=2 放两个物品,求的就是
那
我们假设
是不是很明显了呢,
到这里就可以了,依次类推,动态转移方程为
但是好像还有一些问题没考虑完.........
2、需要单独考虑的问题
看回例子:
| 物品编号 | 物品重量 | 物品价值 |
|---|---|---|
| 1 | 5 | 20 |
| 2 | 6 | 10 |
| 3 | 4 | 12 |
我们知道
3、一维优化
我们刚是用二维来存状态的,那可不可以压缩到一维呢?
答案是可以的,其实我们发现上面的
三、代码
1、二维数组
#include<bits/stdc++.h>
using namespace std;
int w[105],val[105];
int dp[105][1005];
int main()
{
int t,m,res=-1;
scanf("%d%d",&t,&m);
for(int i=1;i<=m;i++) scanf("%d%d",&w[i],&val[i]);
for(int i=1;i<=m;i++)
for(int j=t;j>=0;j--)
if(j>=w[i]) dp[i][j]=max(dp[i-1][j-w[i]]+val[i],dp[i-1][j]);
else dp[i][j]=dp[i-1][j];
printf("%d",dp[m][t]);
return 0;
}
2、一维数组
#include<bits/stdc++.h>
using namespace std;
int aa[1000001],bb[1000001],f[1000001];
int a,b,c,d;
int main()
{
scanf("%d%d",&a,&b);
for(int i=1;i<=b;++i) scanf("%d%d",aa+i,bb+i);
for(int i=1;i<=b;i++)
{
for(int j=aa[i];j<=a;j++)
{
f[j]=max(f[j],f[j-aa[i]]+bb[i]);
}
}
printf("%d",f[a]);
}