您的位置:首页 > 其它

hdu 1059 Dividing

2013-10-01 09:44 246 查看

1.题目

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

2.分析

1.本题要求平分物品,所以资源上限应该为总价值的一半,因此当资源限制为奇数的时候无法平分,应该去掉;

2.为了要达到价值的一半而进行物品的选择,可以按照01背包的思路针对每类物品的每一个商品进行01背包,记录中间产生的值和资源限制进行比较;但是,01背包速度较慢,没有优化,详见《背包九讲》。

3.由于不是要完全都选择,只是选择其中的部分,可以对每一类物品使用多重背包来搞即可,同时可以利用多重背包的优化策略。根据最后的要求判断最优值是否等于资源限制的一半即可。

3.复杂度

时间复杂度是O(V*Σn[i]);空间复杂度O(V);

4.涉及内容

动态规划

5.感想

关于背包初始化有两种情况:

1)背包不要求装满:初始化的时候,在任何一个价值限制下,0肯定都满足题目要求不装满,根据动态规划由前边导出后边值的时候0是一个满足条件的值。

2)背包要求装满:初始化的时候,在0价值限制下,0肯定满足要求装满;在非零价值线之下,由于是初始化,自然没有任何数值满足条件要求,因此可以初始化为整形最大值或者整形最小值,此时,在推导的时候都需要考虑上一次的价值是否是在装满条件下的(即不是整形最大值或者最小值,而是新计算出来的值)。判断的方法:当初始化为最小值的时候,用f[v]=max{f[v],f[v-cost]+weight};当初始化为最大值的时候,用f[v]=min{f[v],f[v-cost]+weight};或者用if判断f[v-cost]是否是初始化的值即可。

对于本题这种组合形式,可以再01背包函数和完全背包函数中各自加上装满情况的初始化,自己判断。最后,将结果和初始化值作比较即可。

第二个感悟还是要把经典题目弄清楚,弄明白!!!!

6.代码

#include <iostream>
using namespace std;
int c1059[7],f1059[60005];
long total1059=0,limitvalue1059=0,num1059=0;
bool cin1059()
{
memset(c1059,0,sizeof(c1059));
memset(f1059,0,sizeof(f1059));
total1059=limitvalue1059=0;
cin>>c1059[1]>>c1059[2]>>c1059[3]>>c1059[4]>>c1059[5]>>c1059[6];
for(int i=6;i>=1;--i)
{
total1059+=c1059[i]*i;
}
return (c1059[1]||c1059[2]||c1059[3]||c1059[4]||c1059[5]||c1059[6]);
}

int max1059(int a,int b) { return a>b?a:b; }

void ZeroOnePack1059(int c,int w)
{
for(int i=limitvalue1059;i>=c;--i)
f1059[i]=max1059(f1059[i],f1059[i-c]+w);
}
void CompletePack1059(int c,int w)
{
for(int i=c;i<=limitvalue1059;++i)
f1059[i]=max1059(f1059[i],f1059[i-c]+w);
}
void MultiplePack1059(int c,int w,int n)
{
if(c*n>=limitvalue1059)
{
CompletePack1059(c,w);
}
else
{
int k=1;
while(k<n)
{
ZeroOnePack1059(c*k,w*k);
n-=k;//一下两条语句的顺序很重要
k+=k;
}
ZeroOnePack1059(c*n,w*n);
}
}

int main()
{
//freopen("in.txt","r",stdin);
while(cin1059())
{
if(total1059%2)
{
cout<<"Collection #"<<++num1059<<":"<<endl<<"Can't be divided."<<endl<<endl;
continue;
}
limitvalue1059=total1059/2;
for(int i=1;i<=6;++i)
{
MultiplePack1059(i,i,c1059[i]);
}
if(f1059[limitvalue1059]==limitvalue1059)
cout<<"Collection #"<<++num1059<<":"<<endl<<"Can be divided."<<endl<<endl;
else
cout<<"Collection #"<<++num1059<<":"<<endl<<"Can't be divided."<<endl<<endl;
}
return 0;
}


7.参考文献

1./article/5183073.html

2.http://java-mans.iteye.com/blog/1646457

3./article/1969921.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: