您的位置:首页 > 其它

HDU 2079 选课时间(题目已修改,注意读题) 母函数 || 多重背包

2011-05-11 22:00 405 查看
今天做这题才知道原来母函数的原型不是从第二个括号开始,那不过是优化而已,除了1^n,2^n那种类型可以从2开始外其他都要从1开始。好了,上代码吧。

#include<stdio.h>
int n,k,m1[450],m2[450],t,a,b;
int num[15],sc[15];
void gf( )
{
for( int i = 0; i <= num[1];i++ )
m1[i*sc[1]] = 1;
for( int i = 2; i <= k;++i )
{
for( int j = 0; j <= n; ++j )
for( int l = 0; l <= num[i] && j+l*sc[i] <= n; ++l )
m2[j+l*sc[i]] += m1[j];
for( int j = 0; j <= n; ++j )
m1[j] = m2[j],m2[j] = 0;
}
}
int main( )
{
scanf( "%d",&t );
while( t-- )
{
scanf( "%d%d",&n,&k );
for( int i = 0; i <= n; ++i )
m1[i] = m2[i] = 0;
for( int i = 1; i <= k; ++i )
{
int a,b;
scanf( "%d%d",&sc[i],&num[i] );
}
gf(  );
printf( "%d\n",m1
);
}
return 0;
}


其实这题也可以用背包写怎么写呢。。 因为数量有限制,所以这是个多重背包,数量和分数分别是他的一个限制。这是别人写出来的。话说看了好久没懂,最后在时雨的点拨下才明白。话说看懂这里后,我对小雨的DP思想又有深入一层的理解了。

其实应该像小雨讲的,我们不能把背包分得那么清楚。 终于明白为神马这两个循环跟“正常”的多重背包写法不同了,这两个循环第一就是从后面往前面,这样就保证了在选的时候不会重复( 前面的不会影响后面的,其实这个我也是听时雨说的,后来我选了n久,终于有点明白了,要是前面选了的话后面的也会把这个给包容进去,所以要从后面往前面,这样前面的就不会影响后面的 )。相信读者还有一点不明白,就是每一次选的是都是从1到num[i]个,难道前面选的这些都是连续的吗???那样就会有多种选法了,其实这个不用考虑,因为这是一个组合,不是排列,所以不用考虑它连不连续( 前面已经有其他的学分选择了,我只要把这种学分中n个“塞”进去就可以了,不用考这n个是分别“塞在哪里”,只要塞进去就可以了,因为这是组合),大概就这么多了,不懂的大家可以提问

#include<stdio.h>
#include<string.h>
int sc[10],num[10],dp[50],n,k;
int main( )
{
int t;
scanf( "%d",&t );
while( t-- )
{
scanf( "%d%d",&n,&k );
memset( dp,0,sizeof( dp ) );
for( int i = 1; i <= k; ++i )
scanf( "%d%d",&sc[i],&num[i] );
dp[0] = 1;
for( int i = 1; i <= k; ++i )
for( int j = n; j >= sc[i]; --j )
for( int l = 1;l <= num[i] && j >= l * sc[i] ; ++l )
dp[j] += dp[j - l * sc[i]];
printf( "%d\n",dp
);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: