状压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;
}