8223. Tiling a Grid With Dominoes
We wish to tile a grid 4 units high and N units long with rectangles (dominoes) 2 units by one unit (in either orientation). For example, the figure shows the five different ways that a grid 4 units high and 2 units wide may be tiled.
Write a program that takes as input the width, W, of the grid and outputs the number of different ways to tile a 4-by-W <tex2html_verbatim_mark>grid.
The first line of input contains a single integer N, (1<=N<=1000) which is the number of datasets that follow.
Each dataset contains a single decimal integer, the width, W, of the grid for this problem instance.
3 2 3 7
1 5 2 11 3 781
dp[i]表示宽度为i的排列种数。
我们可以这样分解dp[i]:
将i列依次分解为2部分,依次分解为 (i-1)列+1列 (i-2)列+2列 …… 1列+(i-1)列
那么dp[i] = dp[i-1]*dp[1] + dp[i-2]*dp[2] + ……+dp[1][i-1] -R
R是重复的个数,事实上我们不必算出R,只要在计算dp[i-j]*dp[j]的时候去除掉与前面相同情况的个数即可。
首先,dp[0] = dp[1] = 1, dp[2] = 5.
少一列,最后一列的2个只能都是竖的对不对,所以是左边部分是dp[i-1],右边部分是dp[1]。少两列,左边部分是dp[i-2],右边部分是dp[2]-1=4。
如图,为了防止跟少1列的情况重复,所以倒数第二列不能2个竖的,剩下的几种可能画个图就明白。
少j列,依然用这种思路,为了保证不跟前面的情况重复,我们倒数第j列必然不能是2个竖的。所以剩下4种可能,画图填充,就知道有几种可能。
例如,少3列的时候,只有2种情况,所以dp[i-3]*2
画着画着就知道:j ≥ 3时
少奇数列的时候(也就是j为奇数的时候),总数为dp[i-j]*2
少偶数列的时候(也就是j为偶数的时候),总数为dp[i-j]*3
所以状态转移方程就来啦:
dp[i]=dp[i-1]+4*dp[i-2]+2*(dp[i-3]+dp[i-5]...)+3*(dp[i-4]+dp[i-6]...)
#include <cstdlib> #include <iostream> using namespace std; #define Max 1002 int dp[Max]; void init() { dp[0] = 1; dp[1] = 1; dp[2] = 5; for (int i = 3; i <= Max; i++) { dp[i] = dp[i-1] + 4*dp[i-2]; for(int j = 3; j <= i; j++) if(j%2) dp[i] += 2*dp[i-j]; else dp[i] += 3*dp[i-j]; } } int main() { init(); int m, n, cases = 1; cin >> m; while (m--) { cin >> n; cout << cases++ <<" "<< dp[n] <<endl; } }