ZOJ 1100 Mondriaan's Dream

中等难度的DP。铺砖问题,有组合数学公式。 但是用搜索+dp的方法更……好吧,也很难做。

研究了一个下午的标程,终于搞懂。把每一层的砖块压缩为二进制编码,搜索上一层到当前层的状态转化是否能够达到。然后从0到11……11Dp。

void dfs ( int n, int from, int to ) 表示当前从左往右有n块砖,from表示前n块砖在这一层的编码,to表示下一层。修改了一下,使得1表示填满,0表示空位。标程里居然是01倒过来写的,我足足发呆了一个钟头。

其他没什么好说的,对于当前和下一层,每次放砖块只有三种可能:两横,竖放,竖放不下。横空就是两个竖放不下……

 

#include  < cstdio >
#include 
< string >

double  b[ 13 ][ 3000 ];
int  tran[ 20000 ][ 2 ];

int  H, W, maxMove, nTran;

void  dfs (  int  n,  int  from,  int  to )
{
    
if ( n > W )
        
return;
    
if ( n == W )
    
{
        tran[nTran][
0= from;
        tran[nTran 
++][1= to;
        
return;
    }

    dfs ( n 
+ 2, ( from << 2 ) + 3, ( to << 2 ) + 3 );
    dfs ( n 
+ 1, ( from << 1 ) + 1, to << 1 );
    dfs ( n 
+ 1, from << 1, ( to << 1 ) + 1 );
}


void  dp ()
{
    memset ( b, 
0x00sizeof ( b ) );
    b[
0][( 1 << W ) - 1= 1;
    
int i, j;
    
for ( i = 0; i < H; i ++ )
        
for ( j = 0; j < nTran; j ++ )
            b[i 
+ 1][tran[j][1]] += b[i][tran[j][0]];
}


int  main ()
{
    freopen ( 
"in.txt""r", stdin );
    
while ( scanf ( "%d %d"&H, &W ) )
    
{
        
if ( !H )
            
break;
        
int t;
        
if ( H < W )
        
{
            t 
= H; H = W; W = t;
        }

        nTran 
= 0;
        dfs ( 
000 );
        
//pt ();
        dp ();
        
//pb ();
        printf ( "%.0f ", b[H][( 1 << W ) - 1] );
    }

    
return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值