现在的位置: 首页 > 综合 > 正文

hdu 2191 多重背包问题

2013年04月10日 ⁄ 综合 ⁄ 共 1014字 ⁄ 字号 评论关闭

急!灾区的食物依然短缺!
为了挽救灾区同胞的生命,心系灾区同胞的你准备自己采购一些粮食支援灾区,现在假设你一共有资金n元,而市场有m种大米,每种大米都是袋装产品,其价格不等,并且只能整袋购买。
请问:你用有限的资金最多能采购多少公斤粮食呢?

后记:
人生是一个充满了变数的生命过程,天灾、人祸、病痛是我们生命历程中不可预知的威胁。
月有阴晴圆缺,人有旦夕祸福,未来对于我们而言是一个未知数。那么,我们要做的就应该是珍惜现在,感恩生活——
感谢父母,他们给予我们生命,抚养我们成人;
感谢老师,他们授给我们知识,教我们做人
感谢朋友,他们让我们感受到世界的温暖;
感谢对手,他们令我们不断进取、努力。 
同样,我们也要感谢痛苦与艰辛带给我们的财富~
问题分析:本题主要解决在有限的资源下,如何才能买到更多的物品,每种物品数量有限。
采取策略:如果每个物品只有一个,那显然是01背包问题,所我们可以把一个物品直接分开变成01背包问题,这是最简单的思维转换。在转换过程中,发现如果n>m/w,可以看成是可以无限取即完全背包问题。这样就可以解决了,我刚开始也是这样A掉的。但是精益求精吗,在分的时候有讲究,可以运用二进制的思想,即分成1,2,4,。。。。。这样可以优化为O(logn*v);

代码如下:

#include<cstdio>
#include<string>
using namespace std;
int main()
{
int w[1000],n[1000],v[1000],m,x,p,i,j,f[1000],k,a,b;
scanf("%d",&x);
while(x--)
{
memset(f,0,sizeof(f));
scanf("%d%d",&m,&p);
for(i=1;i<=p;i++)
scanf("%d%d%d",&w[i],&v[i],&n[i]);
for(i=1;i<=p;i++)
{
k=1;
while(k<n[i])
{
a=k*w[i];
b=k*v[i];
for(j=m;j>=a;j--)
{
if(f[j]<f[j-a]+b)
f[j]=f[j-a]+b;
}
  n[i]=n[i]-k;
  k=k*2;
}
k=n[i];
             a=k*w[i];
b=k*v[i];
for(j=m;j>=a;j--)
{
if(f[j]<f[j-a]+b)
f[j]=f[j-a]+b;
}
}
printf("%d\n",f[m]);
}
}

思想的转化才是真正智慧,只有能够运用知识才是真正的学会知识

抱歉!评论已关闭.