您的位置:首页 > 其它

hdu 2602 - Bone Collector

2017-02-13 18:48 323 查看

1. 地址

http://acm.hdu.edu.cn/showproblem.php?pid=2602

2. 定位

动态规划

0-1背包

3. 分析

3.1 典型0-1背包

状态转移方程为 dp[i,v]=max(dp[i−1,v],dp[i−1,v−volume[i]]+value[i])。

dp[i,v] 表示前 i 件物品经选择后放入容量为 v 的背包中获得的最优解(总价格最大),该值可以在前 i−1 件物品最优解的基础上得到:

不放入第 i 件物品,即 dp[i,v]=dp[i−1,v]

放入第 i 件物品,同时为其加入腾出足够的空间容量,即 dp[i,v]=dp[i−1,v−volume[i]]+value[i]

放入第 i 件物品可能意味着在前i−1 件物品中少放入部分物品,丢西瓜捡芝麻。因此,二者比较取最大值即为问题的最优解。

3.2 存储空间优化

分析状态转移方程,dp[i,v] 仅与 dp[i−1,v] 和 dp[i−1,v−volume[i]] 有关,采用二维数组完整地存储 dp[1][],dp[2][],...,dp[i−1][] 是一种存储空间上的浪费,我们需要的只是 dp[i−1][]。另外,由于 dp[i−1][x]x<=v,采用数组逆序更新的方式可以保证上一状态的先使用后更新。

因此,将问题的存储空间由二维数组优化为一维数组,状态转移方程为 dp[v]=max(dp[v],dp[v−volume[i]]+value[i])。

3.3 边界处理

dp[0] 看似荒谬,实则是有意义的:

v−volume[i] 很容易出现非正数的情况:v−volume[i]<0 说明背包无法容纳第 i 件物品,舍去;v−volume[i]=0 相当于在背包中装入首个物品。

dp[0] 表示背包容量为0时背包的总价格,它不一定为0。若某物品体积为0且价格不为0,则背包容量为0时其价格也为正数,这是本题陷阱之一

不论题中有无此陷阱,建议保留 dp[0],尽量避免特殊情况的处理,保证算法逻辑的一般性。

4. 代码

#include <stdio.h>
#include <stdlib.h>

#define MAX_N 1001

int volume[MAX_N];
int value[MAX_N];
int dp[MAX_N];

int main()
{
int T,N,V;
int i,j;

scanf("%d*c",&T);
while(T--)
{
scanf("%d*c",&N);
scanf("%d*c",&V);
memset(volume,0,sizeof(volume));
memset(value,0,sizeof(value));
memset(dp,0,sizeof(dp));
for(i=1; i<=N; i++)
{
scanf("%d*c",&value[i]);
}
for(i=1; i<=N; i++)
{
scanf("%d*c",&volume[i]);
}
for(i=1; i<=N; i++)
{
for(j=V; j>=volume[i]; j--)
{
dp[j] = dp[j-volume[i]] + value[i] > dp[j] ? dp[j-volume[i]] + value[i] : dp[j];
}
}
printf("%d\n",dp[V]);
}
return 0;
}


5. 性能

Exe.TimeExe.MemoryCode LengthLanguage
31MS1516K840Bc

6. 未解决问题

6.1 无符号整型的处理效率

在本题中,将数组声明为无符号整型,运算超时;声明为有符号整型后,则顺利通过。对此,提出以下几点猜想:

无符号数运算耗时

memset()
对无符号数的操作耗时

Ver 1.0 2017-9-18
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: