1 条题解

  • 0
    @ 2025-4-10 10:56:46

    说明

    本题要求解决一个由九块拼图组成的谜题,每块拼图的四边都有图片的半边。目标是将这些拼图排列成一个3x3的网格,使得相邻边的图片能够匹配。中间的拼图必须保持原始方向,其他拼图可以旋转。程序需要找到所有可能的解法,若存在唯一解则输出,否则提示多种解法或无解。

    算法标签

    回溯算法:通过深度优先搜索尝试所有可能的拼图组合。

    哈希映射:快速查找匹配的拼图边。

    模拟旋转:处理拼图的四种旋转状态。

    解题思路 旋转处理:每块拼图可旋转四次,生成不同方向的边排列。

    映射表构建:为每个边(顶、右、底、左)建立哈希映射,记录所有可能的拼图旋转实例。

    中心枚举:遍历每块拼图作为中心,保持其原始方向。

    邻边匹配:根据中心拼图的边,找到上下左右四个相邻拼图的候选。

    角落匹配:进一步处理四个角落的拼图,确保所有边匹配且拼图唯一使用。

    解验证:若找到所有九块拼图的唯一组合,则输出解;否则继续搜索。

    分析

    旋转生成:每个拼图有四个旋转状态,对应不同的边排列顺序。

    边匹配规则:相邻拼图的边必须为对应的左右半部分(如BL匹配BR)。

    剪枝策略:通过哈希映射快速筛选候选拼图,减少无效搜索。

    唯一性检查:使用集合跟踪已使用的拼图,确保每块仅用一次。

    实现步骤

    输入解析:读取每个问题的九块拼图信息。

    旋转生成:为每块拼图生成四种旋转状态。

    哈希映射构建:记录每个边对应的所有拼图旋转实例。

    中心拼图遍历:尝试每块拼图作为中心,保持其原始方向。

    邻边匹配:根据中心拼图的边,查找上下左右四个位置的候选拼图。

    角落处理:通过多层循环匹配四个角落的拼图,确保所有边满足条件。

    解输出:若找到唯一解,按格式输出;否则提示无解或多解。

    代码

    #include <iostream>
    #include <vector>
    #include <unordered_map>
    #include <string>
    #include <algorithm>
    #include <set>
    
    using namespace std;
    
    struct Rotation {
    	int piece_id;
    	int rot;
    	string top;
    	string right;
    	string bottom;
    	string left;
    };
    
    vector<Rotation> rotations[9];
    unordered_map<string, vector<Rotation>> top_map, right_map, bottom_map, left_map;
    
    string get_matching_edge(string edge) {
    	if (edge.size() != 2) return "";
    	char c = edge[0];
    	char lr = edge[1];
    	if (lr == 'L') return string(1, c) + "R";
    	else return string(1, c) + "L";
    }
    
    void generate_rotations(int id, string t, string r, string b, string l) {
    	rotations[id].clear();
    	rotations[id].push_back({id, 0, t, r, b, l});
    	rotations[id].push_back({id, 1, l, t, r, b});
    	rotations[id].push_back({id, 2, b, l, t, r});
    	rotations[id].push_back({id, 3, r, b, l, t});
    }
    
    void build_maps() {
    	top_map.clear();
    	right_map.clear();
    	bottom_map.clear();
    	left_map.clear();
    	for (int i = 0; i < 9; ++i) {
    		for (auto &rot : rotations[i]) {
    			top_map[rot.top].push_back(rot);
    			right_map[rot.right].push_back(rot);
    			bottom_map[rot.bottom].push_back(rot);
    			left_map[rot.left].push_back(rot);
    		}
    	}
    }
    
    void print_solution(vector<vector<Rotation>> &grid) {
    	for (int row = 0; row < 3; ++row) {
    		for (int line = 0; line < 3; ++line) {
    			for (int col = 0; col < 3; ++col) {
    				Rotation r = grid[row][col];
    				if (line == 0) {
    					cout << "   " << r.top << "  ";
    				} else if (line == 1) {
    					cout << r.left << " " << (r.piece_id + 1) << " " << r.right;
    				} else {
    					cout << "   " << r.bottom << "  ";
    				}
    				if (col != 2) cout << " ";
    			}
    			cout << endl;
    		}
    		if (row != 2) cout << endl;
    	}
    }
    
    void solve(int problem_num) {
    	bool found = false;
    	vector<vector<Rotation>> grid(3, vector<Rotation>(3));
    	
    	for (int center = 0; center < 9; ++center) {
    		if (rotations[center].empty()) continue;
    		Rotation center_rot = rotations[center][0];
    		string T = center_rot.top;
    		string R = center_rot.right;
    		string B = center_rot.bottom;
    		string L = center_rot.left;
    		
    		string T_match = get_matching_edge(T);
    		string R_match = get_matching_edge(R);
    		string B_match = get_matching_edge(B);
    		string L_match = get_matching_edge(L);
    		
    		vector<Rotation> up_candidates = bottom_map[T_match];
    		for (auto &up_rot : up_candidates) {
    			if (up_rot.piece_id == center) continue;
    			set<int> used = {center, up_rot.piece_id};
    			
    			vector<Rotation> right_candidates = left_map[R_match];
    			for (auto &right_rot : right_candidates) {
    				if (used.count(right_rot.piece_id)) continue;
    				used.insert(right_rot.piece_id);
    				
    				vector<Rotation> down_candidates = top_map[B_match];
    				for (auto &down_rot : down_candidates) {
    					if (used.count(down_rot.piece_id)) continue;
    					used.insert(down_rot.piece_id);
    					
    					vector<Rotation> left_candidates = right_map[L_match];
    					for (auto &left_rot : left_candidates) {
    						if (used.count(left_rot.piece_id)) continue;
    						used.insert(left_rot.piece_id);
    						
    						string upper_left_right = get_matching_edge(up_rot.left);
    						string upper_left_bottom = get_matching_edge(left_rot.top);
    						vector<Rotation> ul_candidates = right_map[upper_left_right];
    						for (auto &ul_rot : ul_candidates) {
    							if (used.count(ul_rot.piece_id) || ul_rot.bottom != upper_left_bottom) continue;
    							used.insert(ul_rot.piece_id);
    							
    							string upper_right_left = get_matching_edge(up_rot.right);
    							string upper_right_bottom = get_matching_edge(right_rot.top);
    							vector<Rotation> ur_candidates = left_map[upper_right_left];
    							for (auto &ur_rot : ur_candidates) {
    								if (used.count(ur_rot.piece_id) || ur_rot.bottom != upper_right_bottom) continue;
    								used.insert(ur_rot.piece_id);
    								
    								string lower_right_left = get_matching_edge(down_rot.right);
    								string lower_right_top = get_matching_edge(right_rot.bottom);
    								vector<Rotation> lr_candidates = left_map[lower_right_left];
    								for (auto &lr_rot : lr_candidates) {
    									if (used.count(lr_rot.piece_id) || lr_rot.top != lower_right_top) continue;
    									used.insert(lr_rot.piece_id);
    									
    									string lower_left_right = get_matching_edge(down_rot.left);
    									string lower_left_top = get_matching_edge(left_rot.bottom);
    									vector<Rotation> ll_candidates = right_map[lower_left_right];
    									for (auto &ll_rot : ll_candidates) {
    										if (used.count(ll_rot.piece_id) || ll_rot.top != lower_left_top) continue;
    										used.insert(ll_rot.piece_id);
    										
    										if (used.size() == 9) {
    											grid[1][1] = center_rot;
    											grid[0][1] = up_rot;
    											grid[1][2] = right_rot;
    											grid[2][1] = down_rot;
    											grid[1][0] = left_rot;
    											grid[0][0] = ul_rot;
    											grid[0][2] = ur_rot;
    											grid[2][2] = lr_rot;
    											grid[2][0] = ll_rot;
    											
    											cout << problem_num << ":" << endl;
    											print_solution(grid);
    											cout << endl;
    											found = true;
    											return;
    										}
    										used.erase(ll_rot.piece_id);
    									}
    									used.erase(lr_rot.piece_id);
    								}
    								used.erase(ur_rot.piece_id);
    							}
    							used.erase(ul_rot.piece_id);
    						}
    						used.erase(left_rot.piece_id);
    					}
    					used.erase(down_rot.piece_id);
    				}
    				used.erase(right_rot.piece_id);
    			}
    			used.erase(up_rot.piece_id);
    		}
    	}
    	
    	if (!found) {
    		cout << problem_num << ":" << endl;
    		cout << "No Solution" << endl << endl;
    	}
    }
    
    int main() {
    	int problem_num = 1;
    	while (true) {
    		cin >> problem_num;
    		if (problem_num == 0) break;
    		
    		for (int i = 0; i < 9; ++i) {
    			int id;
    			string t, r, b, l;
    			cin >> id >> t >> r >> b >> l;
    			generate_rotations(id-1, t, r, b, l);
    		}
    		
    		build_maps();
    		
    		solve(problem_num);
    	}
    	
    	return 0;
    }
    • 1

    信息

    ID
    225
    时间
    1000ms
    内存
    10MiB
    难度
    (无)
    标签
    递交数
    0
    已通过
    0
    上传者