多重背包

来源:互联网 发布:tomcat 调用数据库阻塞 编辑:程序博客网 时间:2024/04/29 15:28

        条件是一种物品可以取最多一定的次数。  推荐题目nyoj546题。。http://acm.nyist.net/JudgeOnline/problem.php?pid=546

  这个刚开始没看懂,,,其实这种问题可以转化为01背包问题,。,就是还有优化的空间。。。

方法是:将第i种物品分成若干件物品,其中每件物品有一个系数,这件物品的费用和价值均是原来的费用和价值乘以这个系数。使这些系数分别为1,2,4,...,2^(k-1),n[i]-2^k+1,且k是满足n[i]-2^k+1>0的最大整数。例如,如果n[i]为13,就将这种物品分成系数分别为1,2,4,6的四件物品。//这几个数可以可以相加成你n【i】之内的所有数。。。等于把所有的数都01了一下、、

分成的这几件物品的系数和为n[i],表明不可能取多于n[i]件的第i种物品。另外这种方法也能保证对于0..n[i]间的每一个整数,均可以用若干个系数的和表示,这个证明可以分0..2^k-1和2^k..n[i]两段来分别讨论得出,并不难,希望你自己思考尝试一下。

自己写的模版。。。。


#include<stdio.h>
int f[100];
void com(int w,int c)              //完全背包
{
int j,v=10;
for(j=c;j<=v;j++)
f[j]=f[j]>f[j-c]+w?f[j]:f[j-c]+w;
}
void o1(int w,int c)                //01背包
{
int v=10,j;
for(j=v;j>=c;j--)
f[j]=f[j]>f[j-c]+w?f[j]:f[j-c]+w;
}
void wq(int w,int c,int am)             //多重背包
{
int v=10;
if(am*c>=v)
com(w,c);
else
{
int k=1;
while(k<=am)   //记住这个=号。。。因为这个刷了一上午、。、、
{
o1(k*w,k*c);
am-=k;
k=k*2;
o1(am*w,am*c);
}
}
}
int main()
{


int v=10,c1=2,w1=3,amo1=2,c2=4,w2=5,amo2=2;           //amo代表次数
wq(w1,c1,amo1);
wq(w2,c2,amo2);
printf("%d\n",f[v]);
}

原创粉丝点击