2011.12.26 POJ1293 转化为01背包来做

这个题目自己做得比较满意,至少从思路上来说,非常满意。因为我完全独立思考地把它转化成了一道01背包问题。


不过在做的过程当中也遇到了一个问题。就是01背包选择后,输出方案的时候发现以前一直以为是正确的方法,现在终于发现有漏洞了。


把问题抽象出一个简单一点的模型吧:

一个背包,背包的能承受的重量为上限为V;有N个物品,物品的重量分别为v1,v2...vN.

求最大可能地装满背包(让背包装的东西尽可能重)时,应该选择哪些物品。


解析:这是一个经典的01背包问题。直接利用滚动数组背包就行。然后反向搜索看应该选择那些物品。


经典的代码:

#include <iostream>
using namespace std;


int V;
int N;
int pack[200];
int a[200];
const int INFINITE = 1<<30;
int choose[200];


void ZeroOnePack( const int cost )
{
for(int v = V; v>=cost; --v)
if( pack[v-cost] != -INFINITE )
pack[v] = pack[v] < pack[v-cost] + cost ? pack[v-cost] + cost : pack[v];
}


void get_path(int Stat)
{
for(int i=N-1; i>=0; --i)
{
if( Stat-a[i]>=0 && pack[Stat-a[i]] + a[i] == pack[Stat] )
{
choose[i] = true;
Stat -= a[i];
}
}
}


int main()
{
freopen("in.txt","r",stdin);
scanf("%d %d",&V,&N);
for(int i=0; i<N; ++i)
scanf("%d",a+i);
//init
pack[0] = 0;
for(int i=1; i<=V; ++i)
pack[i] = -INFINITE;
for(int i=0; i<N; ++i)
ZeroOnePack( a[i] );
int Stat = V;
while( pack[Stat] < 0 ){
--Stat;
}
for(int i=0; i<N; ++i)
choose[i] = false;
get_path( Stat );
for(int i=0; i<N; ++i)
if( choose[i] )
printf(" %d",i+1);
printf("\n");
return 0;
}




考虑某组测试:

V = 100

N = 5

物品重量分别为:25 41 33 50 33


那么输出的选择会出现错误:

它会想装满99的重量,但是它会选择第3和第5号这两个物品。


所以教训是:

涉及到输出选择方案时:谨慎使用滚动数组,LRJ说得还是非常在理,不听老人言吃亏在眼前啊。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值