TOJ 1315



题目标题:


Dividing


题目连接:


http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=1315


题目类型:


动态规划 - 多重背包



数据结构:

struct LMIC_MARBLE
{
	int v;		//价值 
	int cnt;	//个数 
};

思路分析:
经典的多重背包问题

只要进行拆分就可以解

石头的价值和重量是相同的值

因为他们既要趋近于平分值

但是又不能超过它


证明:


源代码:

#include 
#include 

using namespace std;

struct LMIC_MARBLE
{
	int v;		//价值 
	int cnt;	//个数 
};

int snt;
int dp[120005];

void _01pack( LMIC_MARBLE p_pack, int p_k )  
{  
    int i;  
      
    p_pack.v *= p_k;  
      
    for( i = snt; i >= p_pack.v ; i -- )  
    {  
        dp[i] = max( dp[i], dp[i - p_pack.v] + p_pack.v );  
    }  
}  
  
void _compack( LMIC_MARBLE p_pack )  
{  
    int i;  
      
    for( i = p_pack.v; i <= snt; i ++ )  
    {  
        dp[i] = max( dp[i], dp[i - p_pack.v] + p_pack.v );  
    }  
}  

void _multpack( LMIC_MARBLE p_mar )
{
	if( p_mar.v * p_mar.cnt >= snt )
	{
		_compack( p_mar );
		return;
	}
	
	int k = 1;
	
	while( k < p_mar.cnt )
	{
		_01pack( p_mar, k );
		p_mar.cnt -= k;
		k *= 2;
	}
	
	_01pack( p_mar, p_mar.cnt );
}

int main()
{
	int i, cas = 1;
	LMIC_MARBLE arr[10] = { 0 };
	
	while( true )
	{
		snt = 0;
		
		for( i = 1; i <= 6; i ++ )
		{
			scanf( "%d", &arr[i].cnt );
			
			arr[i].v = i;
			
			snt += arr[i].cnt * i;
		}
		
		if( !snt )
		{
			break;
		}
		
		printf( "Collection #%d:\n", cas ++ );
		
		if( snt % 2 != 0 )
		{
			puts( "Can't be divided." );
			printf( "\n" );
			continue;
		}
		
		snt /= 2;
		
		memset( dp, 0, sizeof( dp ) );
		
		for( i = 1; i <= 6; i ++ )
		{
			_multpack( arr[i] );
		}
		
		if( dp[snt] == snt )
		{
			puts( "Can be divided." );
		}
		else
		{
			puts( "Can't be divided." );
		}
		
		printf( "\n" );
	}
	
	return 0;
}



你可能感兴趣的:(ACM解题报告)