(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)

操作过程:






















相关推荐
ZhengEnCi18 分钟前
Agent 架构怎么选:从单 Agent 到多 Agent 编排的选型决策指南
算法·架构
程序喵大人32 分钟前
【C++入门】内存模型与资源管理 - 09 shared_ptr 和 weak_ptr 解决共享,也带来代价
开发语言·c++·资源管理·智能指针·内存模型
秋天的怀念_David1 小时前
第二十二夜 · 数字迷雾
java·程序人生·算法
Pniubi1 小时前
力扣283移动零(双指针法)
算法·leetcode·职场和发展
hhb_6181 小时前
大模型落地三重优化实战
人工智能·算法·机器学习
云和数据.ChenGuang2 小时前
光哥说Python RAG 系统需要哪些评估指标:从检索到生成的全链路评测指南
网络·人工智能·python·算法·langchain
jimy13 小时前
C++ 中的 `T&&`:右值引用与转发引用
开发语言·c++
2601_970703833 小时前
工业除湿机租赁:把一份租金合同拆开看
大数据·数据结构·算法·数据库架构·推荐算法
心中有你02143 小时前
Java实现Dijkstra最短路径算法(邻接表 + 优先队列)
java·数据库·算法
hkNaruto4 小时前
【AI】基于大模型的AI游戏地图生成、控制方案:AI Native Game Harness 迁移操作手册
前端·人工智能·游戏