HDU 1085 Holding Bin-Laden Captive! 母函数||背包||递推
水题 。。 直接把所有可能枚举。。 最后找出没有可能的,即系数为0 的最小数
#include<stdio.h> #include<string.h> int s[4] = {0,1,2,5},m1[100000],m2[100000],num[4],max; void gf( ) { memset( m1,0,sizeof( m1 ) ); memset( m2,0,sizeof( m1 ) ); for( int i = 0; i <= num[1]; ++i ) m1[i] = 1; for( int i = 2; i <= 3; ++i ) { for( int j = 0; j <= max; ++j ) for( int k = 0; k <= num[i]; ++k ) m2[j+k*s[i]] += m1[j]; for( int j = 0; j <= max ; ++j ) m1[j] = m2[j],m2[j] = 0; } } int main( ) { while( scanf( "%d%d%d",&num[1],&num[2],&num[3] ),num[1]||num[2]||num[3] ) { int min = 0; max = num[1]+num[2]*2+num[3]*5+1; gf( ); for( int j = 1; j <= max; ++j ) if( !m1[j] ) { min = j; break; } printf( "%d\n",min ); } return 0; }
下面是一神代码,小晨的神代码,仔细想想 。。 是这么回事额。。 如果1 - 4之间的数都能拼凑起来,那么在sum = n1 + n2 * 2 + n3 *5 之间的数肯定都能拼出来了。。 是吧 。。 因为在sum之间的数都可以表示为5 * n + 0, 5 * n + 1,
5 * n + 2,5 * n + 3, 5 * n + 4,所以只要1,2,3,4能拼出来,那么sum以内的数都能拼出来了,那么最小的那个不能拼出来的就是sum + 1,否则,连1,2,3,4都不能拼出来那么最小的那个不能拼出来的就是1,2,3,4中最小的不能拼出来的那个。
#include<stdio.h> int main( ) { int a,b,c; while( scanf( "%d%d%d",&a,&b,&c ),a||b||c ) { if( !a ) puts( "1" ); else if( a + 2 * b < 4 ) printf( "%d\n",a + 2 * b + 1 ); else printf( "%d\n",a + 2 * b + 5 * c + 1 ); } return 0; }
下面是背包写法,背包的思想是怎样的呢??? 其实这个多重背包比较特殊,因为它的重量和价值都是v[i],那么在重量v[i]内如果能装到v[i]的话,那也就说明能够拼出v[i],否则这个肯定拼不出,是吧。。。 哈哈。。
#include<stdio.h> #include<string.h> int num[4],sum,v[4] = { 0 , 1, 2 , 5},dp[10000]; inline int max( int a,int b ) { return a > b ? a : b; } void _01( int v,int w ) { for( int j = sum; j >= v; --j ) dp[j] = max( dp[j-v] + w,dp[j] ); } void complete( int v,int w ) { for( int j = v; j <= sum; ++j ) dp[j] = max( dp[j-v] + w,dp[j] ); } void multiply( int v,int w,int c ) { if( c * v > sum ) complete( v,w ); else { int k = 1; while( c > k ) { _01( k * v, k * w ); c -= k; k << 2; } _01( c * v, c * w ); } } int main( ) { while( scanf( "%d%d%d",&num[1],&num[2],&num[3] ),num[1]|num[2]|num[3] ) { memset( dp,0,sizeof( dp ) ); sum = num[1] + 2 * num[2] + num[3] * 5; for( int i = 1; i <= 3; ++i ) multiply( v[i],v[i],num[i] ); int c = 0; for( int i = 1; i <= sum; ++i ) if( dp[i] != i )//这里就是找最小值 {//找到不能拼出来的那个数 c = i; break; } if( !c ) c = sum + 1; printf( "%d\n",c ); } return 0; }
本人还是新手 ,转载请注明来自Lvsi‘s home