铺瓷砖 状压dp经典问题

该博客探讨了一道经典的状压DP问题,即如何计算用1×2的砖块铺满给定n×m矩形的所有方案数。博主详细解释了题意,指出当砖块竖直放置时会影响下一行,而水平放置则不会。通过分析初始状态和后续状态的约束,得出判断横铺和竖铺的条件,并提出了计算合法状态的策略。最后,博主给出了实现算法的代码片段。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意

给出 n×m的矩形方块,可以往上面铺1×2的砖块,问铺满这个方块的方案有多少种。

题解

砖块可以竖铺和横铺,竖铺的话会影响到下一行,横铺的话不会影响到下一行,这里我们令 1:表示该方块不会影响下一行,0:表示该方块会影响下一行。

条件一:
考虑(i.j)这一格,如果(i-1,j)上是0,那说明(i-1,j)是竖铺的砖块,那么(i,j)便是1,该点不会影响到下一行了。若(i-1,j)1,那么(i,j)可以是0也可以是1。从而可以得知(i,j) | (i-1,j) = 1

条件二:
只有这个条件还是不够的,因为一旦(i-1,j)是横铺的话,那么(i-1,j+1)也是1,现在考虑初始状态,001100,因为第一行是不会有上一行影响他的,所以如果该点时1那么其必定是横铺。根据横铺的性质,必定有两个连续的1,所以我们可以得出第一行合法的状态有哪些。例如010101便是不合法的。

得出了第一行合法的状态后,枚举第二行的状态,首先要满足的便是条件一,其次考虑条件二,因为第二行是会受上一行影响的,所以如果第二行出现(i,j)出现1那不一定是横铺的砖块,因为如果上一行是(i-1,j)0的话,那么(i,j)已经被覆盖了且不会影响下一行。

仔细观察的话可以发现。如果(i-1,j)1同时(i,j)也是1的话那么该处一定是横铺。所以只需两行状态相与(&)为1的点便是横铺,然后便可以判断是否合法(这里有个优化的地方,便是可以预处理出合法的状态有哪些)。

最终一行的答案必须全是1,因为其没有下一行可以影响了。

代码

#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9+7;
int n,m,mark[1<<11];
瓷砖问题是计算机科学中经典的动态规划问题,特别是当涉及在个给定区域内放置不同类型的瓷砖以形成完整图案时。这个过程可以用递归来解决,尤其适合于编写清晰的代码逻辑。下面是个简单的C语言递归函数的例子,用于计算以特定方式瓷砖的可能性: ```c #include <stdio.h> // 定义递归函数 int tile_puzzle(int row, int col, int tiles[], int n) { // 基本情况:最后行或列,直接返回剩余瓷砖的数量 if (row == 0 || col == n) { return tiles[n]; } // 如果当前位置可以放上瓷砖,计算所有可能性 int count = 0; if (tiles[row * n + col] > 0) { tiles[row * n + col]--; count += tile_puzzle(row - 1, col, tiles, n); // 对于每块砖,还可以考虑向右放或者向下放 count += (col == 0 ? 0 : tile_puzzle(row, col - 1, tiles, n)); count += (row == 0 ? 0 : tile_puzzle(row - 1, col, tiles, n)); tiles[row * n + col]++; } return count; } // 主函数入口点 int main() { int tiles[9] = {1, 0, 0, 0, 0, 1, 0, 0, 1}; // 示例瓷砖数组 int n = sizeof(tiles) / sizeof(tiles[0]); printf("Total arrangements: %d\n", tile_puzzle(n - 1, 0, tiles, n)); // 递归计算第行的排列数 return 0; } ``` 在这个代码中,`tile_puzzle`函数接受当前行、列、剩余瓷砖数组和总瓷砖数作为参数,并通过递归处理每种可能的情况,直到达到边界条件。主函数中初始化了个示例瓷砖数组并调用`tile_puzzle`来求解。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值