状态压缩DP

简介: 复习acwing算法基础课的内容,本篇为讲解基础算法:动态规划——状态压缩DP,关于时间复杂度:目前博主不太会计算,先鸽了,日后一定补上。

文章目录

前言

一、动态规划

二、例题,代码

AcWing 291. 蒙德里安的梦想

本题解析

AC代码

AcWing 91. 最短Hamilton路径

本题解析

AC代码

三、时间复杂度


前言

复习acwing算法基础课的内容,本篇为讲解基础算法:动态规划——状态压缩DP,关于时间复杂度:目前博主不太会计算,先鸽了,日后一定补上。


一、动态规划

动态规划(Dynamic Programming,DP)是求解决策过程最优化的过程,个人认为是目前接触的所有算法里最绕的…


这里的题目的解题方法来自于:y总的闫氏dp分析法


二、例题,代码

AcWing 291. 蒙德里安的梦想

本题链接:AcWing 291. 蒙德里安的梦想

本博客提供本题截图:

image.png

image.png

本题解析

image.png

我们只需要把横向的方块选择好后,竖向的方块只有一种情况,故我们所求情况数为我们横向的方块的填放方案数,比如在上图中的蓝色大方格中,我们只需要填好横向的格子:红色的格子,那么其他剩下的即为竖向的格子,只有一种填写方法。


合法化:如果我们填好了横着的小方块,其余剩下的部分可以由竖着的小方块填充满的话则证明该方案合法:按列去看,每一列内部的所有连续空着的小方格的个数需要是偶数

image.png


其余解释在代码中解释

AC代码

#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long LL;
const int N = 12, M = 1 << N;
int n, m;
LL f[N][M];            // 第一维表示列, 第二维表示所有可能的状态,注意要用long long 否则会爆int
vector<int> state[M];
bool st[M];           //存储每种状态是否有奇数个连续的0,奇数为false,偶数为true
int main()
{
    while (cin >> n >> m, n || m)
    {
        //预处理1:利用连续未填格子的奇偶数去筛掉一些情况
        for (int i = 0; i < 1 << n; i ++ )
        {
            int cnt = 0;        //记录连续的0的个数
            bool is_valid = true;
            for (int j = 0; j < n; j ++ )
                if (i >> j & 1)       //如果是 i >> j == 1进入if
                {
                    if (cnt & 1)    //如果cnt是奇数
                    {
                        is_valid = false;
                        break;
                    }
                }
                else cnt ++ ;     
            if (cnt & 1) is_valid = false;    //判断最下面的那一段0的个数
            st[i] = is_valid;
        }
    //预处理2:看第i-2列伸出来的和第i-1列伸出去的是否冲突
        for (int i = 0; i < 1 << n; i ++ )    //对于第i列的所有情况
        {
            state[i].clear();                 //因为有多组输入,故每次操作要清空
            for (int j = 0; j < 1 << n; j ++ )//对于第i - 1列的所有情况
                if ((i & j) == 0 && st[i | j])// j|k 就是第 i-1 列的有几个1,即哪几行是横着放格子的
                    state[i].push_back(j);    //把合法的情况放入数组之中
        }
    //dp:
        memset(f, 0, sizeof f);    //多组输入数据,每次清空
        f[0][0] = 1;
        //按照定义,上一行中的代码指的是已经将前-1列摆好,且从-1列伸出到第0列的方案数为1   (类似空集)
        for (int i = 1; i <= m; i ++ )   //遍历每一列
            for (int j = 0; j < 1 << n; j ++ ) //遍历每一列的所有状态
                for (auto k : state[j])
                    f[i][j] += f[i - 1][k]; //当前列的方案数就等于之前的第 i-1 列所有状态k的和
        cout << f[m][0] << endl;
        //f[m][0]表示 前 m-1 列都处理完,并且第m-1列没有伸出来的所有方案数
    }
    return 0;
}

AcWing 91. 最短Hamilton路径

本题链接:AcWing 91. 最短Hamilton路径

本博客提供本题截图:

image.png

本题解析

image.png

具体解释与代码中讲解

AC代码

#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 20, M = 1 << N;
int n;
int w[N][N];
int f[M][N];
int main()
{
    cin >> n;
    for (int i = 0; i < n; i ++ )
        for (int j = 0; j < n; j ++ )
            cin >> w[i][j];
    memset(f, 0x3f, sizeof f);
    f[1][0] = 0;    //从0出发,经过的点集为1,即到达0这个点,即为0到0
    for (int i = 0; i < 1 << n; i ++ )  //开始枚举所有的情况
        for (int j = 0; j < n; j ++ )   //枚举到达的所有的点
            if (i >> j & 1)             //如果当前的点的集合包括点 j ,进行状态转移
                for (int k = 0; k < n; k ++ )   //枚举从哪一个点转移过来
                    if ((i - (1 << j)) >> k & 1) //去掉点 j 后,仍然包含 k
                        f[i][j] = min(f[i][j], f[i - (1 << j)][k] + w[k][j]);
    cout << f[(1 << n) - 1][n - 1];   //最终输出 f[111...111][n - 1]
    return 0;
}

三、时间复杂度

关于动态规划——状态压缩DP的时间复杂度以及证明,后续会给出详细的说明以及证明过程,目前先鸽了。

目录
相关文章
|
2月前
|
负载均衡 监控 Java
微服务稳定性三板斧:熔断、限流与负载均衡全面解析(附 Hystrix-Go 实战代码)
在微服务架构中,高可用与稳定性至关重要。本文详解熔断、限流与负载均衡三大关键技术,结合API网关与Hystrix-Go实战,帮助构建健壮、弹性的微服务系统。
316 1
微服务稳定性三板斧:熔断、限流与负载均衡全面解析(附 Hystrix-Go 实战代码)
|
JSON API C语言
Qt平台下使用QJson解析JSON字符串
Qt平台下使用QJson解析JSON字符串
445 0
Qt平台下使用QJson解析JSON字符串
|
JSON 安全 数据格式
YYModel JSON和model相互转化
JSON转模型是我们做iOS开发的基础技能,本文将通过[YYModel](https://github.com/ibireme/YYModel)这个框架安全快速的完成JSON到模型的转换,其中还会介绍到一款好用的插件[ESJsonFormat](https://github.com/EnjoySR/ESJsonFormat-Xcode)。
965 0
|
算法 数据处理 区块链
区块链之旅(三)智能合约与共识机制
​ 智能合约是一套以数字形式定义的约定,包括合约参与方可以在上面执行这些约定的协议。智能合约的基本思想是,各种各样的合约条款可以嵌入到我们使用的硬件和软件中,从而使得攻击者需要很大的代价去攻击。
1932 1
区块链之旅(三)智能合约与共识机制
|
消息中间件 存储 监控
Kafka中的这只“千里眼”,你需要知道!!!
Kafka中的这只“千里眼”,你需要知道!!!
Kafka中的这只“千里眼”,你需要知道!!!
|
存储 数据可视化
浅谈组装式的应用
浅谈组装式的应用。
|
存储 自然语言处理 搜索推荐
MemoryIndex(一)(Lucene 8.8.0)
MemoryIndex(一)(Lucene 8.8.0)
734 0
MemoryIndex(一)(Lucene 8.8.0)
|
机器学习/深度学习 人工智能 自然语言处理
中国智能语音产业发展白皮书十大观点发布!科大讯飞市占率国内第一
【新智元导读】上周日,「2020中国语音创新发展高峰论坛暨中国语音产业联盟年会」在天津召开,会上重磅发布了《中国智能语音产业发展白皮书》之十大观点摘要,为我们全面展示了语音行业的现状和未来。
1720 0
中国智能语音产业发展白皮书十大观点发布!科大讯飞市占率国内第一
|
存储 NoSQL 数据库
DM8表空间管理
DM8表空间管理