码迷,mamicode.com
首页 > 其他好文 > 详细

【例题2】数独游戏

时间:2021-07-12 18:25:52      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:std   程序   需要   ret   lse   space   clu   不能   记录   

【例题2】数独游戏 ?
题面 ?

题目描述

数独是一种传统益智游戏,你需要把 \(9\times 9\) 的数独补充完整,使得图中每行、每列、每个 \(3\times 3\) 的九宫格内数字 \(1\sim 9\) 均恰好出现一次。

请编写一个程序填写数独。

输入格式

输入包含多组测试用例。

每个测试用例占一行,包含 \(81\) 个字符,表达数独的 \(81\) 个格内数据(顺序总体由上到下,同行由左到右)。

每个字符都是一个数字或一个 .(表示尚未填充)。

您可以假设输入中的每一个谜题都只有一个解决方案。

文件结尾处包含单词 end 的单行,表示输入结束。

输出格式

每个测试用例,输出一行数据,表示填充完全后的数独。

样例

样例输入

4.....8.5.3..........7......2.....6.....8.4......1.......6.3.7.5..2.....1.4......
......52..8.4......3...9...5.1...6..2..7........3.....6...1..........7.4.......3.
end

样例输出

417369825632158947958724316825437169791586432346912758289643571573291684164875293
416837529982465371735129468571298643293746185864351297647913852359682714128574936
分析 ?
  • 根据题意,要填数字(废话)
  • 根据题意,\(81\) 个字符组成 \(9\times 9\) 的地图,并且地图中每行、每列、每个 \(3\times 3\) 的九宫格中的数字是 \(1\sim 9\),且不能重复,对于这一个的处理简单,用数组标记就可以了
bool a[9][9], b[9][9], c[9][9][9];

或者是用状态压缩(状压)

int a[9], b[9], c[9][9];
  • 那么剩下的就是枚举爆搜了
Code ?
#include <bits/stdc++.h>
using namespace std;

string s;
int maze[9][9]; // 答案数组
int mat[3][3], line[9], row[9]; // 小矩阵,行,列的数字选择判断数组 

bool dfs(int idx) {
	if (idx == 81) {
		for (int i = 0; i < 9; ++i)
			for (int j = 0; j < 9; ++j)
				cout << maze[i][j];
		cout << endl;
		return true;
	}
	
	int x = idx / 9, y = idx % 9;
	
     // 如果这个位置已经有数字了,那么直接下一个
	if (maze[x][y]) 
		return dfs(idx + 1);
	
	for (int i = 1; i <= 9; ++i) {
         // 判断没有重复数字
		if ((mat[x / 3][y / 3] >> i) & 1) continue;
		if ((line[x] >> i) & 1) continue;
		if ((row[y] >> i) & 1) continue;
		
         // 记录该小矩阵,行,列有该数字
		mat[x / 3][y / 3] |= (1 << i);
		line[x] |= (1 << i);
		row[y] |= (1 << i);
		
		maze[x][y] = i;
		
         // 如果枚举成功,那么唯一的答案已经输出了,没必要继续下去,所以剪掉剩余的所有情况
		if (dfs(idx + 1))
			return true;
		
         // 如果枚举失败,说明(x, y)这个点不适合填 i
		maze[x][y] = 0;
		
         // 将该数字从记录中排除
		mat[x / 3][y / 3] ^= (1 << i);
		line[x] ^= (1 << i);
		row[y] ^= (1 << i);
	}
	
	return false;
}

int main (void) {
	while (cin >> s && s != "end") {
		memset(maze, 0, sizeof(maze));
		memset(mat, 0, sizeof(mat));
		memset(line, 0, sizeof(line));
		memset(row, 0, sizeof(row));
		
		for (int i = 0; i < 9; ++i)
			for (int j = 0; j < 9; ++j) {
				if (s[i * 9 + j] != ‘.‘) {
					maze[i][j] = s[i * 9 + j] - 48;
					
                      // 记录该小矩阵,行,列有该数字
                      mat[i / 3][j / 3] |= (1 << (s[i * 9 + j] - 48));
					line[i] |= (1 << (s[i * 9 + j] - 48));
					row[j] |= (1 << (s[i * 9 + j] - 48));
				}
			}
		
		dfs(0);
	}
	
	return 0;
}

【例题2】数独游戏

标签:std   程序   需要   ret   lse   space   clu   不能   记录   

原文地址:https://www.cnblogs.com/Juro/p/15001717.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有
迷上了代码!