(C++回溯算法)微信小程序“开局托儿所”游戏

问题描述

给定一个矩阵 A = ( a i j ) m × n \bm A=(a_{ij}){m\times n} A=(aij)m×n,其中 a i j ∈ { 1 , 2 , ⋯   , 9 } a{ij}\in\{1,2,\cdots,9\} aij∈{1,2,⋯,9},且满足 ∑ i = 1 m ∑ j = 1 n a i j \sum\limits_{i=1}^m\sum\limits_{j=1}^na_{ij} i=1∑mj=1∑naij被10整除。玩家每次操作需要选择 A \bm A A中某个所有非空元素之和为10的子矩阵,并将其中所有的元素都标记为空。求按何种顺序消除能将 A \bm A A中所有的元素都标记为空,若存在则返回该解决方案,否则返回空列表。

代码

nursery_game.h

cpp 复制代码
#ifndef NURSERY_GAME
#define NURSERY_GAME
#include <vector>
#include <stdint.h>
struct Operate {
	uint8_t x1, y1, x2, y2;
	Operate() {}
	Operate(uint8_t i1, uint8_t j1, uint8_t i2, uint8_t j2):x1(i1), y1(j1), x2(i2), y2(j2) {}
};
std::vector<Operate> solve(int8_t *data, uint8_t m, uint8_t n);
#endif

nursery_game.cpp

cpp 复制代码
#include "nursery_game.h"
#include <utility>
using std::vector;

// #define RECOVER_DATA // 若希望不改变A的值请解开本行注释

#define handle(x1,y1,x2_start,tag) for(uint8_t x2=x2_start;x2<m;){uint8_t ie=x2*n;for(uint8_t y2=y1;y2<n;y2++){uint8_t sum=0;for(uint8_t i=is;i<=ie;i+=n)for(uint8_t j=i+y1,e=i+y2;j<=e;j++){int8_t t=A[j];if(t>0&&(sum+=t)>10)goto tag;}if(sum!=10)continue;vector<uint8_t> set;for(uint8_t i=is;i<=ie;i+=n)for(uint8_t j=i+y1,e=i+y2;j<=e;j++){int8_t t=A[j];if(t>0){A[j]=-t;set.push_back(j);}}R.emplace_back(x1,y1,x2,y2);unRemoveCount-=set.size();posSet.push_back(std::move(set));goto F_push;}tag:x2++;}

// A: 矩阵A数据,逐行排列
// m: 矩阵A行数
// n: 矩阵A列数
vector<Operate> solve(int8_t *A, uint8_t m, uint8_t n) {
	vector<Operate> R;
	vector<vector<uint8_t>> posSet;
	Operate op;
	uint8_t unRemoveCount = m * n, is;
F_push:
	if (!unRemoveCount) {
#ifdef RECOVER_DATA
		int8_t *p = A + m * n;
		do {
			--p;
			*p = -*p;
		} while (p != A);
#endif
		return std::move(R);
	}
	is = 0;
	for (uint8_t x1 = 0; x1 < m; x1++, is += n)
		for (uint8_t y1 = 0; y1 < n; y1++)
			handle(x1, y1, x1, F1)
F_pop:
	if (R.empty()) return {};
	op = R.back();
	R.pop_back();
	unRemoveCount += posSet.back().size();
	for (auto pos : posSet.back()) A[pos] = -A[pos];
	posSet.pop_back();
	is = op.x1 * n;
	handle(op.x1, op.y1, op.x2 + 1, F2)
	for (uint8_t y1 = op.y1 + 1; y1 < n; y1++) handle(op.x1, y1, op.x1, F3)
	for (uint8_t x1 = op.x1 + 1; x1 < m; x1++) {
		is += n;
		for (uint8_t y1 = 0; y1 < n; y1++) handle(x1, y1, x1, F4)
	}
	goto F_pop;
}

test.cpp

cpp 复制代码
#include "nursery_game.h"
#include <stdio.h>
using namespace std;

int main() {
	int8_t data[] = { 4,7,3,3,6,5,4,4,2,1,8,4,2,2,2,6,1,2,3,2,3,2,7,1,2,8,1,3,1,6,4,5,4,5,1,4,2,2,2,3,8,3,3,1,9,2,3,3,1,1,4,4,1,9,3,7,1,3,2,5,3,1,1,5 };
	vector<Operate> r(solve(data, 8, 8));
	for (auto op : r) printf("(%d,%d) (%d,%d)\n", op.x1, op.y1, op.x2, op.y2);
	return 0;
}

测试结果

复制代码
(0,1) (0,2)
(0,0) (2,1)
(0,0) (3,1)
(0,7) (1,7)
(1,3) (1,6)
(0,4) (3,4)
(1,3) (5,3)
(0,3) (2,5)
(0,3) (4,5)
(0,4) (6,4)
(2,0) (2,6)
(0,2) (4,2)
(0,2) (4,6)
(5,0) (7,0)
(5,7) (6,7)
(6,0) (7,2)
(5,0) (6,3)
(0,1) (5,6)
(0,5) (7,5)
(4,0) (6,7)
(3,7) (7,7)
(0,0) (7,7)

操作过程:






















相关推荐
fqbqrr3 小时前
2606C++,C++构的多态
开发语言·c++
小欣加油4 小时前
leetcode56 合并区间
c++·算法·leetcode·职场和发展
lqqjuly4 小时前
前沿算法深度解析(二)
人工智能·算法·机器学习
Yolo_TvT5 小时前
C++:析构函数
c++
徐小夕5 小时前
万字长文!千万级文档 RAG 知识库系统落地实践
前端·算法·github
akunkuntaimei6 小时前
2026年高考数学各省真题及答案(完整版)
算法·高考
Hello:CodeWorld6 小时前
C 风格变参 vs C++ 变参模板:核心区别与选型指南
c语言·c++·算法
漫友也是程序猿7 小时前
ddraw.dll异常排查:旧游戏图形接口、兼容性模式和DirectX组件检查
程序人生·游戏·电脑
8Qi88 小时前
LeetCode 516:最长回文子序列
算法·leetcode·职场和发展·动态规划
搬砖魁首9 小时前
基础能力系列 - 多线程2 - 条件变量
c++·rust·条件变量·原子类型·线程同步互斥