您的位置:首页 > 其它

HDU 1059 Dividing

2013-03-04 23:25 106 查看
题意:有6种大理石(marble,怀疑是不是大理石的意思。。。几块大理石也值得争?!),每种若干件且每种大理石有一定的价值(分别为1,2,3,4,5,6)。问能否分成价值相等的两份。

分析:多重背包。价值和费用相同。注意初始化。以下有两种解法。。。

代码1(多重背包):



#include<iostream>
using namespace std;

int f[60005],num[7];
int sum,half;
const int INF=0x3f3f3f3f;

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

void ZeroOnePack(int c){
int i;
for(i=half;i>=c;i--)
f[i]=max(f[i],f[i-c]+c);
}

void CompletePack(int c){
int i;
for(i=c;i<=half;i++)
f[i]=max(f[i],f[i-c]+c);
}

int main()
{
//freopen("in.txt","r",stdin);
int i,j,k,cas=1;
while(1){
for(i=1,sum=0;i<=6;i++){
scanf("%d",&num[i]);
sum+=num[i]*i;
}
if(sum==0) break;
if(sum%2){
printf("Collection #%d:\n",cas++);
printf("Can't be divided.\n\n");
continue;
}
half=sum/2;
f[0]=0;
for(i=1;i<=half;i++)
f[i]=-INF;
for(i=k=1;i<=6;i++){
if(i*num[i]>=half)
CompletePack(i);
else{
while(k<num[i]){
ZeroOnePack(k*i);
num[i]-=k;
k<<=1;
}
ZeroOnePack(num[i]*i);
}
}
printf("Collection #%d:\n",cas++);
if(f[half]==half) printf("Can be divided.\n\n");
else              printf("Can't be divided.\n\n");
}
return 0;
}


代码2(可行性解法):



#include<iostream>
using namespace std;

int f[7][60005],num[7];
int sum,half;

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

int main()
{
//freopen("in.txt","r",stdin);
int i,j,cas=1;
while(1){
for(i=1,sum=0;i<=6;i++){
scanf("%d",&num[i]);
sum+=num[i]*i;
}
if(sum==0) break;
if(sum%2){
printf("Collection #%d:\nCan't be divided.\n\n",cas++);
continue;
}
half=sum/2;
f[0][0]=0;
for(i=1;i<=half;i++)
f[0][i]=-1;
for(i=1;i<=6;i++){
for(j=0;j<=half;j++)
if(f[i-1][j]>=0)
f[i][j]=num[i];
else f[i][j]=-1;
for(j=0;j<=half-i;j++)
if(f[i][j]>0)
f[i][j+i]=max(f[i][j+i],f[i][j]-1);
}
printf("Collection #%d:\n",cas++);
if(f[6][half]>=0) printf("Can be divided.\n\n");
else              printf("Can't be divided.\n\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: