地址
http://acm.hdu.edu.cn/showproblem.php?pid=2546
定位
动态规划
0-1背包问题变形
分步求解
分析
首先, 判断该问题是0-1背包问题, 理由有二:
(1) N种菜品, 每种菜品取0、1份。
(2) 约束条件为不超过总金额, 目标在求菜价最大值
本题较经典0-1背包问题的不同之处:
(1) 物品重量与价值相同, 每种菜品的花费具有双重属性。
(2) 目标是获得最少的余额, 等价于求最大的总价值。
(3) 看似’无限’的背包容量。在整个拾取过程中, ‘无限’最多出现一次, 即最后一次才可能出现’跨越5元’的购买, 或者说一旦’跨越5元’就停止购买。
分二步求解该问题:
(1) 最后一次购买, 不管能否’跨越5元’, 都应该购买价值最大的物品, 以获取最大的总价值。
(2) 前若干次购买, 一定不能’跨越5元’, 即 N=n−1,V=m−5 的0-1背包问题。
代码
#include <stdio.h>
#include <stdlib.h>
#define MAX_N 1000
int value[MAX_N];
int dp[MAX_N];
int main()
{
int m,n;
int i,j,t;
scanf("%d*c",&n);
while(n)
{
memset(value,0,sizeof(value));
memset(dp,0,sizeof(dp));
for(i=1,j=1;i<=n;i++)
{
scanf("%d*c",&value[j]);
if(value[j] > value[0])
{
t = value[j];
value[j] = value[0];
value[0] = t;
}
j++;
}
scanf("%d*c",&m);
if(m >= 5)
{
for(i=value[1];i<=m-5;i++)
{
dp[i] = value[1];
}
for(i=2;i<=n;i++)
{
for(j=m-5;j>=value[i];j--)
{
dp[j] = dp[j-value[i]] + value[i] > dp[j] ? dp[j-value[i]] + value[i] : dp[j];
}
}
printf("%d\n",m-dp[m-5]-value[0]);
}
else
{
printf("%d\n",m);
}
scanf("%d*c",&n);
}
return 0;
}
性能
Exe.Time | Exe.Memory | Code Length | Language |
---|---|---|---|
31MS | 1420K | 1123B | c |
总结
最大值的分离
根据解题需求, 应从输入的N维向量中分离出最大值。不仅找到, 还要分离, 涉及到存储变化。
(1) 排序, 最大值处于首尾, 实现分离, O(nlogn)
(2) 输入过程中, 边判断边存储, O(n)
Ver 2.0 2017-2-18