Tiling a Grid With Dominoes
Time Limit: 1000/500 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 410 Accepted Submission(s): 321
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 grid.
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
总结了三种方法
1.用dp[n][m]表示排到第n列时,且第n列的状态为m(用四位2进制数表示,0表示未覆盖,1表示覆盖)时的方法数。其中m只可能取值1001=9,1100=12,0011=3,0110=6,0000=0,1111=15(思考其他的情况为什么不成立)
初始化:dp[1][0]=dp[1][3]=dp[1][6]=dp[1][12]=dp[1][15]=1;
状态转移:
dp[t][15]=dp[t-1][15]+dp[t-1][12]+dp[t-1][3]+dp[t-1][6]+dp[t-1][0];
dp[t][9] =dp[t-1][6];
dp[t][12]=dp[t-1][15]+dp[t-1][3];
dp[t][3] =dp[t-1][15]+dp[t-1][12];
dp[t][6] =dp[t-1][15]+dp[t-1][9];
dp[t][0] =dp[t-1][15];
实现的时候把t从2到1000列举就搞定了;
2.
方法二的本质和一相同,不过实现的时候将行变成列,列变成行,用1表示影响下一行,0表示不影响下一行,再用dfs(该函数计算的是下一行可能情况的值)一一列举所有的情况,即考虑了从0000~1111所有的情况。
dp[i][s]表示i行第i行状态为s的值,那么dp[n][0]就表示所求的了
关键代码:
void dfs(int s1,int s2,int p,int n)//s1为当前行状态。s2为构造的下一行状态。p为处理到第几列,n为行数。
{
if(p>3)//一行处理完了。
{
dp[n+1][s2]+=dp[n][s1];
return;
}
if(s1&(1<<p))
dfs(s1,s2,p+1,n);//已被铺上砖,换到下一列
else
{
dfs(s1,s2|(1<<p),p+1,n);//竖着放
if(p<=2&&!(s1&(1<<(p+1))))//横着放
dfs(s1,s2,p+2,n);
}
}
注意初始化dp[0][0]=1,其他全为0;
3.
此方法就是直接找规律了
状态转移方程:
dp[i]=dp[i-1]+4*dp[i-2]+2*(dp[i-3]+dp[i-5]+dp[i-7].+dp[i-奇数]..)+3*(dp[i-4]+dp[i-6]..-dp[i-偶数]..);
解释:将此整体分为两部分列1~k和k+1~i列,即sk=(不可竖向分割的有k列的整体的)*dp[i-(i-k)],然后对sk从k=1积分到k=i-1