题目标题:
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;
}