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;
}
相关推荐
虫小宝2 小时前
返利app排行榜系统设计:基于大数据计算的实时排名算法实现
大数据·算法
千里马-horse2 小时前
CallbackInfo
c++·node.js·napi·callbackinfo
C雨后彩虹2 小时前
字符串拼接
java·数据结构·算法·华为·面试
LYFlied2 小时前
【每日算法】LeetCode 279. 完全平方数(动态规划)
前端·算法·leetcode·面试·动态规划
何小义的AI进阶路2 小时前
win下 vscode下 C++和opencv的配置与使用
c++·图像处理·vscode·opencv
scx201310043 小时前
20251201换根DP总结
算法·动态规划·换根dp
zd2005723 小时前
STREAMS指南:环境及宿主相关微生物组研究中的技术报告标准
人工智能·python·算法
TechNomad3 小时前
排序算法:基数排序算法
算法·排序算法
努力学算法的蒟蒻3 小时前
day43(12.24)——leetcode面试经典150
算法·leetcode·面试