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
浙公网安备 33010602011771号