牛客[编程题] HJ44 Sudoku数独游戏
困难 通过率:27.56% 时间限制:1秒 空间限制:32M
描述
问题描述:数独(Sudoku)是一款大众喜爱的数字逻辑游戏。玩家需要根据9X9盘面上的已知数字,推算出所有剩余空格的数字,并且满足每一行、每一列、每一个3X3粗线宫内的数字均含1-9,并且不重复。
例如:
输入
输出
数据范围:输入一个 9*9 的矩阵
输入描述:
包含已知数字的9X9盘面数组[空缺位以数字0表示]
输出描述:
完整的9X9盘面数组
示例1
输入:
0 9 2 4 8 1 7 6 3 4 1 3 7 6 2 9 8 5 8 6 7 3 5 9 4 1 2 6 2 4 1 9 5 3 7 8 7 5 9 8 4 3 1 2 6 1 3 8 6 2 7 5 9 4 2 7 1 5 3 8 6 4 9 3 8 6 9 1 4 2 5 7 0 4 5 2 7 6 8 3 1
输出:
5 9 2 4 8 1 7 6 3 4 1 3 7 6 2 9 8 5 8 6 7 3 5 9 4 1 2 6 2 4 1 9 5 3 7 8 7 5 9 8 4 3 1 2 6 1 3 8 6 2 7 5 9 4 2 7 1 5 3 8 6 4 9 3 8 6 9 1 4 2 5 7 9 4 5 2 7 6 8 3 1
个人感觉,这个题目出的不好,有多种答案,但是题目只给出一种答案;只要不符合标准答案,即使满足要求,也无法通过;6个用例只通过了5个;
后面的Check函数不是为了解出答案,而是为了检查输出的结果;
本方法还有改进的空间,目前无法唯一确定某一个值时,都是从可能的选项中默认选择第一个;
其实如果默认第一个的情况下无法解出答案时,可以用Check+Random的方式,也就是每试一次都是从可能的选项中随机选择一个,如果不行就再来一遍;
前提时要先把能唯一确定的最终状态记录下来,后面开始通过无限循环一直进行查找,总能找到答案;
using System; using System.Collections.Generic; public class Program { public static void Main() { string line; List<string> lines = new List<string>(); while ((line = System.Console.ReadLine()) != null) { // 注意 while 处理多个 case lines.Add(line); if (lines.Count == 9) { string[] lineArr; int[,] arr = new int[9, 9]; int answer = 0; bool find; for (int i = 0; i < 9; i++) { line = lines[i]; lineArr = line.Split(" "); for (int j = 0; j < 9; j++) { arr[i, j] = int.Parse(lineArr[j]); } } //最多循环81次 for (int k = 0; k < 81; k++) { if (k == 0) { find = true; } else { find = false; } for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { if (arr[i, j] == 0) { answer = GetAnswer(i, j, arr, find); if (answer != 0) { arr[i, j] = answer; find = true; } } } } //如果已完成,就立即结束循环 if (!HasZero(arr)) { break; } } //输出 for (int i = 0; i < 9; i++) { line = string.Empty; for (int j = 0; j < 9; j++) { line += arr[i, j].ToString(); if (j != 8) { line += " "; } } Console.WriteLine(line); } Check(arr); } } } //获取某个空位的答案 static int GetAnswer(int row, int column, int[,] arr, bool find) { //使用排除法确定可以填写的值 //一共1-9九个,如果排除到只剩一个,那么就可以确定答案了 List<int> left = new List<int>(); for (int i = 1; i <= 9; i++) { left.Add(i); } //从行开始排除 for (int i = 0; i < 9; i++) { if (i == column) continue; left.Remove(arr[row, i]); } if (left.Count == 1) { return left[0]; } //再从列排除 for (int i = 0; i < 9; i++) { if (i == row) continue; left.Remove(arr[i, column]); } if (left.Count == 1) { return left[0]; } //从所在的九宫格排除 for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (row / 3 * 3 + i == row && column / 3 * 3 + j == column) continue; left.Remove(arr[row / 3 * 3 + i, column / 3 * 3 + j]); } } if (left.Count == 1) { return left[0]; } else if (!find && left.Count > 0) { return left[0]; } return 0; } //判定矩阵中是否还有0,也就是判定是否已经完成 static bool HasZero(int[,] arr) { for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { if (arr[i, j] == 0) { return true; } } } return false; } static bool Check(int[,] arr) { if (HasZero(arr)) return false; for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { int answer = GetAnswer(i, j, arr, true); if (answer != arr[i, j]) { Console.WriteLine($"row={i},col={j},answer={answer},real={arr[i, j]}"); return false; } } } return true; } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
2022-11-11 Bert_Doc BERT文档中英文对照版
2022-11-11 BERT论文中文版:用于语言理解的深度双向Transformer的预训练
2022-11-11 BERT模型源码解析