错题-方格填充

方格填充

题目描述

将高为 H,宽为 W 的棋盘分割成若干个宽和高分别为 1 和 2 的长方形,有多少种方案。

输入描述

第一行为 H(1≤H≤11),W(1≤W≤11)。

输出描述

输出方案数。

测试样例

输入:
2 2
输出:
2

题解

用状压DP,用一个数字来表示当前行的每一个虚拟格子的状态

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-naJGvOG7-1657096392296)(C:\Users\YYYYYKN\AppData\Roaming\Typora\typora-user-images\image-20220523231724284.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PcFMgNZL-1657096392297)(C:\Users\YYYYYKN\AppData\Roaming\Typora\typora-user-images\image-20220523232026512.png)]

注意这里的遍历方案数的循环,循环截至的条件是 “<” 而不是小于等于(全 0 也算一种,n 种物品全选的话他表示的方案总数的二进制换成十进制也是 2 n − 1 2^n -1 2n1 ) for (ll s1 = 0; s1 < (1 << W); s1++)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

ll dp[5000][5000] = {0};
bool check(ll s, ll m) //判断是不是连续的0
{
     ll count = 0;
     for (ll i = 0; i < m; i++)
     {
          if ((s & (1 << i)) != 0)
          {
               if ((count & 1) != 0)
                    return false;
               else
                    count = 0;
          }
          else
               count++;
     }
     if ((count & 1) != 0) //加这一步是为了防止最高位的那些0由于更高位没有1就测不到
          return false;
     return true;
}
int main()
{
     ll H, W;
     cin >> H >> W;
     dp[0][0] = 1;

     for (ll i = 1; i <= H; i++)
          for (ll s1 = 0; s1 < (1 << W); s1++)      //当前列方案
               for (ll s2 = 0; s2 < (1 << W); s2++) //上一列方案
                    if ((s1 & s2) == 0 && check(s1 | s2, W))
                         dp[i][s1] += dp[i - 1][s2];

     cout << dp[H][0];
     return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值