TOJ 1315



题目标题:


Dividing


题目连接:


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


题目类型:


动态规划 - 多重背包



数据结构:

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

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

只要进行拆分就可以解

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

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

但是又不能超过它


证明:


源代码:

#include <iostream>
#include <stdio.h>

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;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值