中等難度的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, 0x00, sizeof ( 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 ( 0, 0, 0 );
//pt ();
dp ();
//pb ();
printf ( "%.0f ", b[H][( 1 << W ) - 1] );
}
return 0;
}