ZOJ 1227 Free Candies

记忆化搜索。在表达篮子里糖果的状态时采取位操作。

记录f(x1,x2,x3,x4)代表当第i列娶到xi个时的最大糖果数量。然后……强搜吧,没什么好说的。也许还可以剪枝,但时限在暴力搜索面前都不堪一击。

位操作是相当有趣的hash方法,我得好好练习一下。

#include  < cstdio >
#include 
< string >

int  a[ 40 ][ 4 ], f[ 41 ][ 41 ][ 41 ][ 41 ], N, b[ 5 ], h[ 5 ], x[ 4 ], ans;

void  dp ();
void  dfs (  int int  );
void  pb ();

int  main ()
{
    
//freopen ( "in.txt", "r", stdin );
    while ( scanf ( "%d"&N ) && N )
    
{
        
int i, j;
        
for ( i = 0; i < N; i ++ )
        
{
            
for ( j = 0; j < 4; j ++ )
                scanf ( 
"%d"&a[i][j] );
        }

        
        dp ();
        printf ( 
"%d ", ans / 2 );
    }

    
return 0;
}


void  dp ()
{
    ans 
= 0;
    h[
0= 31;
    
int i;
    
for ( i = 1; i < 5; i ++ )
        h[i] 
= h[i - 1<< 5;
    memset ( f, 
0xffsizeof ( f ) );
    memset ( x, 
0sizeof ( x ) );
    f[
0][0][0][0= 0;
    dfs ( 
00 );
}


void  dfs (  int  hash,  int  num )
{
    
int i, k, t, full, thash = hash, tnum = num;
    full 
= 1;
    
for ( i = 0; i < 5; i ++ )
    
{
        t 
= hash & h[i];
        b[i] 
= t >> ( 5 * i );
        
if ( !b[i] )
            full 
= 0;
    }

    
//pb ();
    if ( full )
        
return;
    
for ( k = 0; k < 4; k ++ )
    
{
        
if ( x[k] < N )
        
{
            
int get = 0;
            
for ( i = 0; i < 5; i ++ )
            
{
                
if ( a[x[k]][k] == b[i] )
                
{
                    hash 
= hash & ( ~h[i] );
                    num 
+= 2;
                    
get = 1;
                    
break;
                }

            }

            
if ( !get )
            
{
                
for ( i = 0; i < 5; i ++ )
                
{
                    
if ( !b[i] )
                    
{
                        hash 
= hash | ( a[x[k]][k] << ( 5 * i ) );
                        
break;
                    }

                }

            }

            x[k] 
++;
            
if ( f[x[0]][x[1]][x[2]][x[3]] < num )
            
{
                f[x[
0]][x[1]][x[2]][x[3]] = num;
                
if ( num > ans )
                    ans 
= num;
                dfs ( hash, num );
            }

            hash 
= thash, num = tnum;
            x[k] 
--;
            
for ( i = 0; i < 5; i ++ )
            
{
                t 
= hash & h[i];
                b[i] 
= t >> ( 5 * i );
            }

            
//pb ();            
        }

    }

}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值