首页 > 其他分享 >状态压缩DP

状态压缩DP

时间:2024-08-05 10:52:52浏览次数:16  
标签:11 状态 cnt int 压缩 一列 DP 方格

状态压缩DP

定义:

状态压缩是一种使用二进制数来表示状态的方法,通常用于表示只有两种状态(0和1)的对象。

Acwing,291 蒙特里安的梦想

291. 蒙德里安的梦想 - AcWing题库

题目概览

求把 N × M N×M N×M的棋盘分割成若干个 1 × 2 1×2 1×2的长方形,有多少种方案。

例如当 N = 2 , M = 4 N=2,M=4 N=2,M=4时,共有 55 55 55种方案。当 N = 2 , M = 3 N=2,M=3 N=2,M=3时,共有 33 33 33种方案。

如下图所示:

2411_1.jpg

输入格式

输入包含多组测试用例。

每组测试用例占一行,包含两个整数 N N N和 M M M。

当输入用例 N = 0 , M = 0 N=0,M=0 N=0,M=0时,表示输入终止,且该用例无需处理。

输出格式

每个测试用例输出一个结果,每个结果占一行。

数据范围

1 ≤ N , M ≤ 11 1≤N,M≤11 1≤N,M≤11

输入样例:
1 2
1 3
1 4
2 2
2 3
2 4
2 11
4 11
0 0
输出样例:
1
0
1
2
3
5
144
51205

思路:

假设我们当前的方格是这样的:

image-20240805095031331

比如,我们先看一个简单情况,在一个 4 ∗ 3 4 * 3 4∗3的小方格中(蓝色),我们已经放好了横向的 2 ∗ 1 2 * 1 2∗1的小格子。

image-20240805095346505

那么,剩下的格子纵向放只有一种情况,只能一列一列放。

所以, 2 ∗ 1 2 * 1 2∗1格子的摆放方案数等价于 2 ∗ 1 2 * 1 2∗1格子横向摆放的方法

f [ i ] [ j ] f[i][j] f[i][j]表示现在要摆第i列,j是一个二进制数,表示上一列有那些行伸出来了小方格到我这一列

FOR EXAMPLE:

比如,我现在在第三列,但是第二行由于上一列放置小方格导致已经被占用了,于是 j = ( 01000 ) 2 j=(01000)_2 j=(01000)2​

image-20240805100620574

即如图的情况

比如此时,矩阵是一个 5 ∗ 5 5 * 5 5∗5的情况,所以j是一个5位的二进制数,即 0 < = j < = 31 0 <= j <= 31 0<=j<=31

那么,我们如何转移呢?枚举一下 i − 1 i - 1 i−1列的所有状态

FOR EXAMPLE:

比如,我们当前要算的状态是这样的 f [ 3 ] [ 1 ] f[3][1] f[3][1]往前推,当前状态的表示图( j = ( 00001 ) 2 j = (00001)_2 j=(00001)2​)为:

image-20240805101519461

此时,我们枚举的上一个状态的j(称他为k)是 k = ( 10010 ) 2 k = (10010)_2 k=(10010)2​,判断一下这个状态能否转移过来

能否转移过来的条件很简单:

  1. j和k不能有冲突,如果冲突了,就会出现这样的情况:

    image-20240805102003861

    那如何判断呢?利用位运算就可以啦~

    (j & k) == 0时,即 j j j和 k k k是没有冲突的。

  2. 同一列上剩余的连续的空白格子一定是偶数个,不然竖着没法放

    image-20240805102635841

    判断方式:j | k不存在连续奇数个0

    时间复杂度: 4 ∗ 1 0 7 4 * 10^7 4∗107

代码实现:

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

const int N = 12,M = 1 << N;

int n ,m;//行数列数
long long f[N][M];//DP数组
bool st[M];//标记

int main(){
    while(cin >> n >> m,n || m){//只要n,m不等于0就一直做
        memset(f,0,sizeof f);//清一下f
        
        //预处理是否出现连续奇数个0
        for(int i = 0;i < 1 << n;i++){
            st[i] = true;//假设它是成立的然后再来判断
            int cnt = 0;//存储当前这段连续0的个数
            for(int j = 0;j < n;j++)
                if(i >> j & 1){//如果这一位是1
                    if(cnt & 1) st[i] = 0;//如果发现是奇数个,那么不成立
                    cnt = 0;//cnt清零
                }
                else cnt++;//否则是0,继续累加
                
            if(cnt & 1) st[i] = 0;//最后cnt还需要判断一下
        }
    
        f[0][0] = 1;
        for(int i = 1;i <= m;i++)
            for(int j = 0;j < 1 << n;j++)
                for(int k = 0;k < 1 << n;k++)
                    if((j & k) == 0 && st[j | k])
                        f[i][j] += f[i - 1][k];
                    
        cout << f[m][0] << endl;
    }
    
}

标签:11,状态,cnt,int,压缩,一列,DP,方格
From: https://blog.csdn.net/Lucky_Threewsr/article/details/140921243

相关文章

  • 常见CMS漏洞(WordPress、DeDeCMS、ASPCMS、PHPMyadmin、Pageadmin)
    目录一:WordPress步骤一:进入Vulhub靶场并执行以下命令开启靶场;在浏览器中访问并安装好子...步骤二:思路是修改其WP的模板写入一句话木马后门并访问其文件即可GetShel;登陆WP后点击【外观】--》【编辑】--》404.php步骤三:访问以下连接即可获取WebShel...姿势二:上传主......
  • Luogu P1777 帮助 题解 [ 紫 ] [ 线性 dp ] [ 状压 dp ]
    帮助:大毒瘤!!!调了我2h,拍了我2h,最后没调出来,重写才AC。wdnmd。思路这题主要是线性dp,而状压dp只是最后在统计答案时的一个辅助。首先定义\(dp[i][j][k]\)为考虑前\(i\)本书,已经抽出来了\(j\)本,最后没被抽出来的一本书是高度\(k\)的最小混乱度。每次放入的书与最后一位......
  • 深入剖析Apache Flink的状态后端
    ApacheFlink的状态后端是其状态管理的核心组件,负责存储和管理Flink程序的状态信息。状态后端的选择直接影响到Flink程序的容错能力、性能以及与外部系统的集成能力。本文将详细介绍Flink中的不同状态后端,包括它们的工作原理、特点、适用场景以及如何配置和使用。一、Flink......
  • 简析传输层协议——TCP、UDP协议
    TCP/IP协议族的传输层协议TCP(TransmissionControlProtocol)传输控制协议UDP(UserDatagramProtocol)用户数据报协议TCP协议介绍:TCP是面向连接的、可靠的进程到进程通信的协议TCP提供全双工服务,即数据可在同一时间双向传输TCP报文段:TCP将若干个字节构成一个分......
  • CF1995D-状态压缩
    CF1995D-状态压缩大致题意你是一名语言学家,正在研究一种神秘的古代语言。你知道它的单词只由拉丁字母的前c个字母组成。每个单词都有一个大小写,可以通过其最后一个字母明确地确定(不同的字母对应不同的大小写)。例如,单词"ABACABA"和"ABA"(如果存在的话)在该语言中具有相......
  • 数据结构之特殊矩阵的压缩存储
    1.对称矩阵的压缩存储定义:若n阶矩阵A满足a(ij)=a(ji)(1≤i,j≤n),则称A为n阶对称矩阵。压缩存储方法:由于对称矩阵上三角和下三角的元素相同(主对角线上的元素只存储一次),因此可以只存储上三角(或下三角)的元素和主对角线上的元素。存储方式:通常使用一维数组来存储这些元素。......
  • 实用好软-----照片压缩软件推荐 拍摄的图片太大 如何无损缩小
                   随着您照片的增多,您是不是觉得电脑的硬盘都快不够用。数码照片压缩是将数码照片文件的大小减小,以便更方便地存储、分享或传输。压缩图像文件可以减少存储空间的需求,同时也可以减少上传或下载图像的时间。以下是几种常见的数码照......
  • DP
    1)数位DP数位DP:用来解决一类特定问题,这种问题比较好辨认,一般具有这几个特征:要求统计满足一定条件的数的数量(即,最终目的为计数);这些条件经过转化后可以使用「数位」的思想去理解和判断;输入会提供一个数字区间(有时也只提供上界)来作为统计的限制;上界很大(比如10^{18}),暴力枚举......
  • 【C++BFS】802. 找到最终的安全状态
    本文涉及知识点C++BFS算法LeetCode802.找到最终的安全状态有一个有n个节点的有向图,节点按0到n-1编号。图由一个索引从0开始的2D整数数组graph表示,graph[i]是与节点i相邻的节点的整数数组,这意味着从节点i到graph[i]中的每个节点都有一条边。如果一......
  • 【Unity XR Input 获取Quest和Pico各个按键状态,按下、抬起、按下中】
    usingSystem;usingSystem.Collections.Generic;usingUnityEngine;usingUnityEngine.XR;usingQFramework;///<summary>///提供各种输入事件///</summary>publicclassInputEvent:MonoSingleton<InputEvent>{//*************输入设别***********......