C++ 状压DP(01矩阵约束问题)

状压DP 01矩阵约束问题 代码框架见下 对应蓝桥云课 蓝桥云课

cpp 复制代码
#include <iostream>
using namespace std;

#define maxn 20
#define maxm 20
#define type long long
int n, m;
#define MaskType (Mask::UP | Mask::LEFT)
#define dptype DPType::NUM
type dp[2][1 << maxm];
int grid[maxn][maxm];
#define mod 100000000

enum DPType {
    MIN = 0,
    MAX = 1,
    NUM = 2,
    MOD = 3,
};

enum GripType {
    EMPTY = -1,
    ZERO = 0,
    ONE = 1
};

enum Mask {
    UP = (1 << 0),
    LEFT = (1 << 1)
};
// 状态转移时的最优函数
type MatrixPutDP_Opt(type cur, type pre, type curOneCount) {
    if (dptype == DPType::MIN) {
        return min(cur, pre + curOneCount);
    }
    else if (dptype == DPType::MIN) {
        return max(cur, pre + curOneCount);
    }
    else if (dptype == DPType::NUM) {
        return cur + pre;
    }
    else {
        return (cur + pre) % mod;
    }
}

type MatrixPutDP_ValueInf() {
    if (dptype == DPType::MIN) {
        return 1000000000;
    }
    else if (dptype == DPType::MIN) {
        return -1000000000;
    }
    else if (dptype == DPType::NUM) {
        return 0;
    }
    else {
        return 0;
    }
}

type MatrixPutDP_ValueInit() {
    if (dptype == DPType::MIN) {
        return 0;
    }
    else if (dptype == DPType::MIN) {
        return 0;
    }
    else if (dptype == DPType::NUM) {
        return 1;
    }
    else {
        return 1;
    }
}


bool MatrixPutDP_canPut(const int prestate, const int curstate, const int r, const int c) {
    if (grid[r][c] != GripType::EMPTY) {
        return false;
    }
    if (MaskType && Mask::UP) {
        if (r > 0 && grid[r - 1][c] == GripType::ONE) {
            return false;
        }
        if (prestate & 1) {
            return false;
        }
    }
    if (MaskType & Mask::LEFT) {
        if (c > 0 && grid[r][c - 1] == GripType::ONE) {
            return false;
        }
        if ((curstate >> 1) & 1) {
            return false;
        }
    }
    return true;
}

void MatrixPutDP_DFS(
    int col,
    const int maxcol,
    const int row,
    const int pre,
    int prestate,
    const int cur,
    int curstate,
    int cnt) {
    if (col == maxcol) {
        //dp[cur][curstate] += dp[pre][prestate];
        dp[cur][curstate] = MatrixPutDP_Opt(dp[cur][curstate], dp[pre][prestate], cnt);
        return;
    }
    for (int i = 0; i < 2; ++i) {
        //首先枚举上一行的01情况
        int pres = prestate << 1 | i;
        for (int j = 0; j < 2; ++j) {
            int curs = (curstate << 1 | j);
            if (j == GripType::ONE) {
                if (!MatrixPutDP_canPut(pres, curs, row, col)) {
                    continue;
                }
            }
            MatrixPutDP_DFS(col + 1, maxcol, row, pre, pres, cur, curs, cnt + j);
        }
    }
}

type MatrixPutDP_Solve(int n, int m) {
    // 1 初始化
    int pre = 0, cur = 1;
    for (int i = 1; i < (1 << m); ++i) {
        dp[pre][i] = MatrixPutDP_ValueInf();
    }
    dp[pre][0] = MatrixPutDP_ValueInit();
    // 2 状态转移
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < (1 << m); ++j) {
            dp[cur][j] = MatrixPutDP_ValueInf();
        }
        MatrixPutDP_DFS(0, m, i, pre, 0, cur, 0, 0);
        swap(pre, cur);
    }
    // 3 状态结算
    type ans = 0;
    for (int j = 0; j < (1 << m); ++j) {
        ans = MatrixPutDP_Opt(ans, dp[pre][j], 0);
    }
    return ans;
}


int main()
{
    cin >> n >> m;
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            grid[i][j] = GripType::EMPTY;
        }
    }
    cout << MatrixPutDP_Solve(n, m) << endl;
    // 请在此输入您的代码
    return 0;
}

代码练习 1 对应蓝桥云课 威震华夏 代码见下

cpp 复制代码
#include <iostream>
using namespace std;

#define maxn 13
#define maxm 13
#define type long long
int n, m;
#define MaskType (Mask::UP | Mask::LEFT)
#define dptype DPType::MOD
type dp[2][1 << maxm];
int grid[maxn][maxm];
#define mod 100000000

enum DPType {
    MIN = 0,
    MAX = 1,
    NUM = 2,
    MOD = 3,
};

enum GridType {
    EMPTY = -1,
    ZERO = 0,
    ONE = 1
};

enum Mask {
    UP = (1 << 0),
    LEFT = (1 << 1)
};
// 状态转移时的最优函数
type MatrixPutDP_Opt(type cur, type pre, type curOneCount) {
    if (dptype == DPType::MIN) {
        return min(cur, pre + curOneCount);
    }
    else if (dptype == DPType::MIN) {
        return max(cur, pre + curOneCount);
    }
    else if (dptype == DPType::NUM) {
        return cur + pre;
    }
    else {
        return (cur + pre) % mod;
    }
}

type MatrixPutDP_ValueInf() {
    if (dptype == DPType::MIN) {
        return 1000000000;
    }
    else if (dptype == DPType::MIN) {
        return -1000000000;
    }
    else if (dptype == DPType::NUM) {
        return 0;
    }
    else {
        return 0;
    }
}

type MatrixPutDP_ValueInit() {
    if (dptype == DPType::MIN) {
        return 0;
    }
    else if (dptype == DPType::MIN) {
        return 0;
    }
    else if (dptype == DPType::NUM) {
        return 1;
    }
    else {
        return 1;
    }
}


bool MatrixPutDP_canPut(const int prestate, const int curstate, const int r, const int c) {
    if (grid[r][c] != GridType::EMPTY) {
        return false;
    }
    if (MaskType && Mask::UP) {
        if (r > 0 && grid[r - 1][c] == GridType::ONE) {
            return false;
        }
        if (prestate & 1) {
            return false;
        }
    }
    if (MaskType & Mask::LEFT) {
        if (c > 0 && grid[r][c - 1] == GridType::ONE) {
            return false;
        }
        if ((curstate >> 1) & 1) {
            return false;
        }
    }
    return true;
}

void MatrixPutDP_DFS(
    int col,
    const int maxcol,
    const int row,
    const int pre,
    int prestate,
    const int cur,
    int curstate,
    int cnt) {
    if (col == maxcol) {
        //dp[cur][curstate] += dp[pre][prestate];
        dp[cur][curstate] = MatrixPutDP_Opt(dp[cur][curstate], dp[pre][prestate], cnt);
        return;
    }
    for (int i = 0; i < 2; ++i) {
        //首先枚举上一行的01情况
        int pres = prestate << 1 | i;
        for (int j = 0; j < 2; ++j) {
            int curs = (curstate << 1 | j);
            if (j == GridType::ONE) {
                if (!MatrixPutDP_canPut(pres, curs, row, col)) {
                    continue;
                }
            }
            MatrixPutDP_DFS(col + 1, maxcol, row, pre, pres, cur, curs, cnt + j);
        }
    }
}

type MatrixPutDP_Solve(int n, int m) {
    // 1 初始化
    int pre = 0, cur = 1;
    for (int i = 1; i < (1 << m); ++i) {
        dp[pre][i] = MatrixPutDP_ValueInf();
    }
    dp[pre][0] = MatrixPutDP_ValueInit();
    // 2 状态转移
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < (1 << m); ++j) {
            dp[cur][j] = MatrixPutDP_ValueInf();
        }
        MatrixPutDP_DFS(0, m, i, pre, 0, cur, 0, 0);
        swap(pre, cur);
    }
    // 3 状态结算
    type ans = 0;
    for (int j = 0; j < (1 << m); ++j) {
        ans = MatrixPutDP_Opt(ans, dp[pre][j], 0);
    }
    return ans;
}


int main()
{
    cin >> n;
    m = n;
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            int x;
            cin >> x;
            if(x == 1){
              grid[i][j] = GridType::EMPTY;
            }else{
              grid[i][j] = GridType::ZERO;
            }
        }
    }
    cout << MatrixPutDP_Solve(n, m) << endl;
    // 请在此输入您的代码
    return 0;
}

代码练习 2 对应蓝桥云课 小明的宠物袋 代码见下

cpp 复制代码
#include <iostream>
using namespace std;

#define maxn 30
#define maxm 10
#define type long long
int n, m;
#define MaskType (Mask::UP | Mask::LEFT)
#define dptype DPType::MAX
type dp[2][1 << maxm];
int grid[maxn][maxm];
#define mod 100000000

enum DPType {
    MIN = 0,
    MAX = 1,
    NUM = 2,
    MOD = 3,
};

enum GridType {
    EMPTY = -1,
    ZERO = 0,
    ONE = 1
};

enum Mask {
    UP = (1 << 0),
    LEFT = (1 << 1)
};
// 状态转移时的最优函数
type MatrixPutDP_Opt(type cur, type pre, type curOneCount) {
    if (dptype == DPType::MIN) {
        return min(cur, pre + curOneCount);
    }
    else if (dptype == DPType::MAX) {
        return max(cur, pre + curOneCount);
    }
    else if (dptype == DPType::NUM) {
        return cur + pre;
    }
    else {
        return (cur + pre) % mod;
    }
}

type MatrixPutDP_ValueInf() {
    if (dptype == DPType::MIN) {
        return 1000000000;
    }
    else if (dptype == DPType::MAX) {
        return -1000000000;
    }
    else if (dptype == DPType::NUM) {
        return 0;
    }
    else {
        return 0;
    }
}

type MatrixPutDP_ValueInit() {
    if (dptype == DPType::MIN) {
        return 0;
    }
    else if (dptype == DPType::MAX) {
        return 0;
    }
    else if (dptype == DPType::NUM) {
        return 1;
    }
    else {
        return 1;
    }
}


bool MatrixPutDP_canPut(const int prestate, const int curstate, const int r, const int c) {
    if (grid[r][c] != GridType::EMPTY) {
        return false;
    }
    if (MaskType && Mask::UP) {
        if (r > 0 && grid[r - 1][c] == GridType::ONE) {
            return false;
        }
        if (prestate & 1) {
            return false;
        }
    }
    if (MaskType & Mask::LEFT) {
        if (c > 0 && grid[r][c - 1] == GridType::ONE) {
            return false;
        }
        if ((curstate >> 1) & 1) {
            return false;
        }
    }
    return true;
}

void MatrixPutDP_DFS(
    int col,
    const int maxcol,
    const int row,
    const int pre,
    int prestate,
    const int cur,
    int curstate,
    int cnt) {
    if (col == maxcol) {
        //dp[cur][curstate] += dp[pre][prestate];
        dp[cur][curstate] = MatrixPutDP_Opt(dp[cur][curstate], dp[pre][prestate], cnt);
        return;
    }
    for (int i = 0; i < 2; ++i) {
        //首先枚举上一行的01情况
        int pres = prestate << 1 | i;
        for (int j = 0; j < 2; ++j) {
            int curs = (curstate << 1 | j);
            if (j == GridType::ONE) {
                if (!MatrixPutDP_canPut(pres, curs, row, col)) {
                    continue;
                }
            }
            MatrixPutDP_DFS(col + 1, maxcol, row, pre, pres, cur, curs, cnt + j);
        }
    }
}

type MatrixPutDP_Solve(int n, int m) {
    // 1 初始化
    int pre = 0, cur = 1;
    for (int i = 1; i < (1 << m); ++i) {
        dp[pre][i] = MatrixPutDP_ValueInf();
    }
    dp[pre][0] = MatrixPutDP_ValueInit();
    // 2 状态转移
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < (1 << m); ++j) {
            dp[cur][j] = MatrixPutDP_ValueInf();
        }
        MatrixPutDP_DFS(0, m, i, pre, 0, cur, 0, 0);
        swap(pre, cur);
    }
    // 3 状态结算
    type ans = MatrixPutDP_ValueInf();
    for (int j = 0; j < (1 << m); ++j) {
        ans = MatrixPutDP_Opt(ans, dp[pre][j], 0);
    }
    return ans;
}


int main()
{
    cin >> n >> m;
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            int x;
            cin >> x;
            if (x == 0) {
                grid[i][j] = GridType::EMPTY;
            }
            else {
                grid[i][j] = GridType::ZERO;
            }
        }
    }
    cout << MatrixPutDP_Solve(n, m) << endl;
    // 请在此输入您的代码
    return 0;
}

代码练习 3 对应洛谷 01矩阵 P1539 代码见下

cpp 复制代码
#include <iostream>
using namespace std;

#define maxn 20
#define maxm 20
#define type long long
int n, m;
#define MaskType (Mask::UP | Mask::LEFT | Mask::DOWN | Mask::RIGHT)
#define dptype DPType::MOD
type dp[2][1 << maxm];
int grid[maxn][maxm];
#define mod 10007

enum DPType {
    MIN = 0,
    MAX = 1,
    NUM = 2,
    MOD = 3,
};

enum GripType {
    EMPTY = -1,
    ZERO = 0,
    ONE = 1
};

enum Mask {
    UP = (1 << 0),
    LEFT = (1 << 1),
    RIGHT = (1 << 2),
    DOWN = (1 << 3)
};
// 状态转移时的最优函数
type MatrixPutDP_Opt(type cur, type pre, type curOneCount) {
    if (dptype == DPType::MIN) {
        return min(cur, pre + curOneCount);
    }
    else if (dptype == DPType::MIN) {
        return max(cur, pre + curOneCount);
    }
    else if (dptype == DPType::NUM) {
        return cur + pre;
    }
    else {
        return (cur + pre) % mod;
    }
}

type MatrixPutDP_ValueInf() {
    if (dptype == DPType::MIN) {
        return 1000000000;
    }
    else if (dptype == DPType::MIN) {
        return -1000000000;
    }
    else if (dptype == DPType::NUM) {
        return 0;
    }
    else {
        return 0;
    }
}

type MatrixPutDP_ValueInit() {
    if (dptype == DPType::MIN) {
        return 0;
    }
    else if (dptype == DPType::MIN) {
        return 0;
    }
    else if (dptype == DPType::NUM) {
        return 1;
    }
    else {
        return 1;
    }
}


bool MatrixPutDP_canPut(const int prestate, const int curstate, const int r, const int c) {
    if (grid[r][c] != GripType::EMPTY) {
        return false;
    }
    if (MaskType && Mask::UP) {
        if (r > 0 && grid[r - 1][c] == GripType::ONE) {
            return false;
        }
        if (prestate & 1) {
            return false;
        }
    }
    if (MaskType & Mask::LEFT) {
        if (c > 0 && grid[r][c - 1] == GripType::ONE) {
            return false;
        }
        if ((curstate >> 1) & 1) {
            return false;
        }
    }
    if (MaskType & Mask::RIGHT) {
        if (c + 1 < m && grid[r][c + 1] == GripType::ONE) {
            return false;
        }
    }

    if (MaskType & Mask::DOWN) {
        if (r + 1 < n && grid[r + 1][c] == GripType::ONE) {
            return false;
        }
    }
    return true;
}

void MatrixPutDP_DFS(
    int col,
    const int maxcol,
    const int row,
    const int pre,
    int prestate,
    const int cur,
    int curstate,
    int cnt) {
    if (col == maxcol) {
        //dp[cur][curstate] += dp[pre][prestate];
        dp[cur][curstate] = MatrixPutDP_Opt(dp[cur][curstate], dp[pre][prestate], cnt);
        return;
    }
    for (int i = 0; i < 2; ++i) {
        //首先枚举上一行的01情况
        int pres = prestate << 1 | i;
        for (int j = 0; j < 2; ++j) {
            int curs = (curstate << 1 | j);
            if (j == GripType::ONE) {
                if (!MatrixPutDP_canPut(pres, curs, row, col)) {
                    continue;
                }
            }
            MatrixPutDP_DFS(col + 1, maxcol, row, pre, pres, cur, curs, cnt + j);
        }
    }
}

type MatrixPutDP_Solve(int n, int m) {
    // 1 初始化
    int pre = 0, cur = 1;
    for (int i = 1; i < (1 << m); ++i) {
        dp[pre][i] = MatrixPutDP_ValueInf();
    }
    dp[pre][0] = MatrixPutDP_ValueInit();
    // 2 状态转移
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < (1 << m); ++j) {
            dp[cur][j] = MatrixPutDP_ValueInf();
        }
        MatrixPutDP_DFS(0, m, i, pre, 0, cur, 0, 0);
        swap(pre, cur);
    }
    // 3 状态结算
    type ans = 0;
    for (int j = 0; j < (1 << m); ++j) {
        ans = MatrixPutDP_Opt(ans, dp[pre][j], 0);
    }
    return ans;
}

char mat[maxn][maxn];

int main()
{
    cin >> n >> m;
    for (int i = 0; i < n; ++i) {
        cin >> mat[i];
    }
    if (n > m) {
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < m; ++j) {
                if (mat[i][j] == '0') {
                    grid[i][j] = ZERO;
                }
                else if (mat[i][j] == '1') {
                    grid[i][j] = ONE;
                }
                else {
                    grid[i][j] = EMPTY;
                }
            }
        }
    }
    else {
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < m; ++j) {
                if (mat[i][j] == '0') {
                    grid[j][i] = ZERO;
                }
                else if (mat[i][j] == '1') {
                    grid[j][i] = ONE;
                }
                else {
                    grid[j][i] = EMPTY;
                }
            }
        }
        swap(n, m);
    }
    cout << MatrixPutDP_Solve(n, m) << endl;
    return 0;
}
相关推荐
石山代码39 分钟前
C++ 内存分区 堆区
java·开发语言·c++
心中有国也有家44 分钟前
cann-recipes-infer:昇腾 NPU 推理的“菜谱集合”
经验分享·笔记·学习·算法
绝知此事1 小时前
【算法突围 01】线性结构与哈希表:后端开发的收纳术
java·数据结构·算法·面试·jdk·散列表
碧海银沙音频科技研究院1 小时前
通话AEC与语音识别AEC的软硬回采链路
深度学习·算法·语音识别
csdn_aspnet2 小时前
Python 算法快闪 LeetCode 编号 70 - 爬楼梯
python·算法·leetcode·职场和发展
张小姐的猫3 小时前
【Linux】多线程 —— 线程互斥
linux·运维·服务器·c++
m0_629494735 小时前
LeetCode 热题 100-----26.环形链表 II
数据结构·算法·leetcode·链表
壹号用户5 小时前
用队列实现栈
数据结构·算法
做人求其滴5 小时前
面试经典 150 题 380 274
c++·算法·面试·职场和发展·力扣