HDU 2079 选课时间(题目已修改,注意读题) 母函数 || 多重背包
今天做这题才知道原来母函数的原型不是从第二个括号开始,那不过是优化而已,除了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[n] ); } 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[n] ); } return 0; }
本人还是新手 ,转载请注明来自Lvsi‘s home