您的位置:首页 > 其它

hdu 1059 Dividing (多重背包 )

2013-04-06 10:01 330 查看
这一道题目和 hdu2844/article/9562225.html 是同一个类型,都可以用多重背包写,都有一个共同点就是标记为bool值比较好理解,但是这一个道也可以用分组背包写的,不过这是一个看做没有任何要求的背包(不是至少,最多一个之类的了),那么就可以看做是 01 背包了,再进一步转化成了多重背包,所以多重背包只是无特殊要求的分组背包的特例,刚好优化后就是多重背包了


Time Limit Exceeded 的 分组背包

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define CLR(arr,val) memset(arr,val,sizeof(arr));
const int MAX = 120001;
int dp[MAX];
int a[7];
int V;
int main()
{
//freopen("in.txt","r",stdin);
int ncase = 0;
while(true)
{
ncase ++;
int flag = false;
V = 0;
for(int i = 1 ;i <= 6;i++)
{
cin>>a[i];
V += ( a[i] * i);
if(a[i] != 0)
flag =true;
}
if(flag == false)
break;
int flag2 = false;
if( V % 2 == 0)
{
V /= 2;
CLR(dp,false);
dp[0] = true;
for(int i = 1;i <= 6;i++)
{
for(int j = 1;j <= a[i] ;j ++ )
{
for(int k = V ;k >= i ;k--)
{
if(dp[k - i] == true)
dp[k] = true;
}
}
}
if(dp[V] == true)
flag2 = true;
}
if(flag2 == false)
cout<<"Collection #"<<ncase<<":"<<endl<<"Can't be divided."<<endl<<endl;
else
cout<<"Collection #"<<ncase<<":"<<endl<<"Can be divided."<<endl<<endl;
}
return 0;
}


经过二进制优化后变成了多重背包,能ac

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
#define CLR(arr,val) memset(arr,val,sizeof(arr))
#define max(a,b) a > b ? a : b
const int MAX = 120001;
bool dp[MAX];
int sum;
void zeroOnePack(int cost ,int value)
{
for(int i = sum ;i >= cost ;i--)
if(dp[i - cost] == true )
dp[i] = true;
}
void completePack(int cost ,int value)
{
for(int i = cost ;i <= sum;i++)
if(dp[i - cost] == true)
dp[i] = true;
}

void multiplePack(int cost ,int value, int amount)
{
if(amount * cost >= sum )
completePack(cost ,value);
else
{
int k = 1;
while(k < amount)
{
zeroOnePack(cost * k ,value * k);
amount -= k;
k *= 2;
}
zeroOnePack(cost * amount ,value * amount);
}
}
int main()
{
int ncase = 0;
//freopen("in.txt","r",stdin);
while(true)
{
ncase ++;
int a[7];
bool flag = false;
CLR(dp,false);
dp[0] = true;
sum = 0;
for(int i = 1 ;i <= 6;i++)
{
cin>>a[i];
sum += (a[i] * i);
if(a[i] !=  0)
flag = true;
}
if(flag == false)
break;
int flag2=false;
if(sum % 2 == 0)
{
sum /= 2;
for(int i = 1;i <= 6;i++)
{
multiplePack(i , 1, a[i]);
}
if(dp[sum] == true)
flag2 = true;
}
if(flag2 == false)
{
cout<<"Collection #"<<ncase<<":"<<endl<<"Can't be divided."<<endl<<endl;
}
else
cout<<"Collection #"<<ncase<<":"<<endl<<"Can be divided."<<endl<<endl;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: