hdu 1059 Dividing--DP-多重背包问题

15 篇文章 0 订阅
/*
	多重背包问题
	该题求的是能否拿到总价值的一半
	可以假设  每个球消耗的空间和它的价值相等
	则本题可转化为:在总空间一半的口袋里能否得到总价值的一半(因为价值密度为1,故最多能达到一半)
*/
#include<stdio.h>
#include<string.h>
int d[120000],n[7],w;
void cpack(int c,int ww)
{
	int j;
	for(j=c;j<=w;j++)
	{
		if((d[j-c]+ww)>d[j])
			d[j]=d[j-c]+ww;
	}
}
void znpack(int c,int ww)
{
	int j;
	for(j=w;j>=c;j--)
	{	
		if(d[j]<(d[j-c]+ww))
			d[j]=d[j-c]+ww;
	}
}
void mpack(int c,int ww,int nn)
{
	
	if(c*nn>=w)
	{
		cpack(c,ww);
		return;
	}
	int k=1;
	while(k<nn)
	{
		znpack(k*c,k*ww);
		nn=nn-k;
		k=k*2;
	}
	znpack(nn*c,nn*ww);
}
int main()
{
	int q=1,i;
	while(1)
	{
		w=0;
		for(i=1;i<=6;i++)
		{
			scanf("%d",&n[i]);
			w+=i*n[i];
		}
		if(!w)
			break;
		if(w%2)
		{
			printf("Collection #%d:\nCan't be divided.\n\n",q++);
			continue;
		}
		w=w/2;
		d[0]=0;
		memset(d,0,sizeof(d));
		for(i=1;i<=6;i++)
		{
			if(!n[i])
				continue;
			mpack(i,i,n[i]);
		}
		if(d[w]!=w)
			printf("Collection #%d:\nCan't be divided.\n\n",q++);
		else printf("Collection #%d:\nCan be divided.\n\n",q++);
	}
	return 0;
}

以上是我仿别人的,我原先自己写的因为数组开小了,系统给了个Runtime Error(ACCESS_VIOLATION),同时没有把球消耗的空间假设为同它的价值,所以只能求:占用总数一半的价值,最多(或最少,最少可以将数组初始化为正无穷,不用判断数据是否合法)能拿到几个球;若d[一般价值]=初始化,则不可以平分。因此,处理比较复杂。

#include<stdio.h>
int d[120000],n[7],w;
void cpack(int c,int ww)
{
    int j;
    for(j=c;j<=w;j++)
    {
        if((d[j-c]+ww)<d[j])
            d[j]=d[j-c]+ww;
    }
}
void znpack(int c,int ww)
{
    int j;
    for(j=w;j>=c;j--)
    {    
        if(d[j]>(d[j-c]+ww))
            d[j]=d[j-c]+ww;
    }
}
void mpack(int c,int ww,int nn)
{
    
    if(c*nn>=w)
    {
        cpack(c,ww);
        return;
    }
    int k=1;
    while(k<nn)
    {
        znpack(k*c,k*ww);
        nn=nn-k;
        k=k*2;
    }
    znpack(nn*c,nn*ww);
}
int main()
{
    int q=1,i;
    while(1)
    {
        w=0;
        for(i=1;i<=6;i++)
        {
            scanf("%d",&n[i]);
            w+=i*n[i];
        }
        if(!w)
            break;
        if(w%2)
        {
            printf("Collection #%d:\nCan't be divided.\n\n",q++);
            continue;
        }
        w=w/2;
        d[0]=0;
        for(i=1;i<=w;i++)
            d[i]=999999999;
        for(i=1;i<=6;i++)
            mpack(i,1,n[i]);
        if(d[w]==999999999)
            printf("Collection #%d:\nCan't be divided.\n\n",q++);
        else printf("Collection #%d:\nCan be divided.\n\n",q++);
    }
    return 0;
}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值