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

/*
	多重背包问题
	该题求的是能否拿到总价值的一半
	可以假设  每个球消耗的空间和它的价值相等
	则本题可转化为:在总空间一半的口袋里能否得到总价值的一半(因为价值密度为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;
}




你可能感兴趣的:(hdu 1059 Dividing--DP-多重背包问题)