HDu 1059 Dividing--DP-多重リュックサック問題

2732 ワード

/*
	      
	               
	                     
	       :                    (       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:
Can't be divided.

",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:
Can't be divided.

",q++); else printf("Collection #%d:
Can be divided.

",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:
Can't be divided.

",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:
Can't be divided.

",q++); else printf("Collection #%d:
Can be divided.

",q++); } return 0; }