这题的作者 CUI, Tianyi, 也就是《背包九讲》的作者 崔天翼 。该题整合了几中典型的背包。所以能完全独立的状况下AC这道题。那么背包问题也就不是问题了。
首先膜拜下大神。 瞻仰下 Jane Street Capital。
下面是解题报告正文:
刚看完题,对于 MM的 another requirement 有点疑问。she want to buy one kind of cookies in each group。
刚开始的理解是只买一个。再阅读一遍后 才看到重点是 kind 一种cookie。侧面反映了阅读尚需提高。
解题思路:
每种物品有个值 K ,K非零时, 代表有购买上线即做完全背包,K为零时代表无购买上线即做多重背包。
对于another requirement ,再开个数组,做动归,购买一种cookie可换得的满意度。
由于group中的cookie 购买K值限制是否挂钩,题目好像没有明确说。所以做题的时候我打算两个都尝试。结果第一次尝试就得到了结果。在数据上应该是无关的。
for i : 1 -> n
begin
if( blong[i] ) // 是否属于某个group
clear( tmp );
if( k[i] )
MultiplePack( blong[i]?tmp:dp );
else
CompletePack( blong[i]?tmp:dp );
if( blong[i] )
for j : 1 -> d
group[ blong[i] ][ j ] = max( group[ blong[i] ][ j ] , tmp[ j ] );//对分组背包的预处理
end
for groupID : 1 -> g
for i : d -> 0
for j : 1 -> i
dp[ i ] = max( dp[i] , dp[i-j] + group[groupID][j] );
贴上AC代码
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define INF 0x3fffffff
#define MAXN 1125
int dp[ MAXN ] , tmp[ MAXN ] , group[ 10 ][ MAXN ];
int n , d , g , blong[ MAXN ] , k[ MAXN ] , e[ MAXN ] , p[ MAXN ];
void ZeroOnePack( int cost , int wight , int f[] ){
for( int i = d ; i >= cost ; --i )
f[i] = max( f[i] , f[i-cost] + wight );
}
void CompletePack( int cost , int wight , int f[] ){
for( int i = cost ; i <= d ; ++ i )
f[i] = max( f[i] , f[ i-cost ] + wight );
}
void MultiplePack( int cost , int wight , int amount , int f[] ){
if( cost * amount >= d ){
CompletePack( cost , wight , f );
return ;
}
int k = 1 ;
while( k < amount ){
ZeroOnePack( cost * k , wight * k , f );
amount -= k ;
k <<= 1 ;
}
ZeroOnePack( cost * amount , wight * amount , f );
}
bool get( int gid ){
int x = 0 ;
char ch;
while( ch = getchar() ){
if( ch == ' ' || ch == '\n' ){
blong[ x-1 ] = gid ;
//printf( " %d" , x );
return ch != '\n' ;
}
x = x*10 + ( ch - '0' ) ;
}
}
void clear( int f[] ){
for( int i = 1 ; i <= d ; ++ i )
f[i] = -INF;
f[0] = 0 ;
}
int main()
{
while( ~scanf( "%d%d" , &n , &d ) ){
for( int i = 0 ; i < n ; ++ i )
{
scanf( "%d%d%d" , &k[i] , &e[i] , &p[i] ) ;
blong[i] = 0;
}
scanf( "%d" , &g );getchar();
for( int i = 1 ; i <= g ; ++ i ) {
clear( group[i] );
while( get( i ) );
}
clear( dp );
for( int i = 0 ; i < n ; ++ i ){
if( blong[i] ) clear( tmp );
if( k[i] )
MultiplePack( p[i] , e[i] , k[i] , blong[i]?tmp:dp );
else
CompletePack( p[i] , e[i] , blong[i]?tmp:dp );
if( blong[i] )
for( int j = 1 ; j <= d ; ++ j )
group[ blong[i] ][ j ] = max( group[ blong[i] ][ j ] , tmp[j] );
}
for( int gid = 1 ; gid <= g ; ++ gid ){
for( int i = d ; i >= 0 ; -- i ){
for( int j = 1 ; j <= i ; ++ j ){
dp[i] = max( dp[i] , dp[i-j] + group[gid][j]);
}
}
}
if( dp[d] >= 0 ) printf( "%d\n" , dp[d] );
else puts( "i'm sorry..." );
}
return 0;
}