你不去做,別人不知道你會做!送給我自己。
題設:在9*9的數獨表格內輸入幾個數字,自動完成數獨;
準備:在充分理解遞歸,回溯之後,完成這個題目就不難了。但是高性能完成就還是得研究。。。。
原理概要:採用棧的數據結構模型存入已經輸入過得數獨表格,此時應該只有幾個表格有數字,我們採用一個標記數字記下這些數字位置,他們是不能進行壓棧和出棧的。然後從第一個格子開始遍歷。驗證a[0] 是否爲空,則插入1,進行驗證。符合數獨。繼續a[1]插入1,不符合數獨則插入2,符合。繼續a[2]插入1,2,3,等等。直到某個數字插入9也不符合數獨的規則的時候,回溯;
原理詳解:
主函數:
using ch.shudu.musoft.com.cn.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Runtime.Serialization.Json;
using ch.shudu.musoft.com.cn.Utils;
using System.Text;
namespace ch.shudu.musoft.com.cn.Controllers
{
public class MainController : Controller
{
//
// GET: /Main/
/// <summary>
/// 主頁面
/// </summary>
/// <returns></returns>
public ActionResult Index()
{
return View();
}
/// <summary>
/// 進入數獨
/// </summary>
/// <param name="json">傳入的Json串</param>
/// <returns></returns>
public string count(string json)
{
Num[] numStack = JsonHelper.DataContractJsonDeserialize<Num[]>(json);
//一位數裝入棧裏面
Map map = ShuDuUtil.toArray(numStack);
//進入計算
while (map.top < 80)
{
for (int i = 1; i < 10; i++)
{
//如果當前棧頂是10,則壓如數字 判斷;否則直接判斷
if (map.stack[map.top] == 10)
{
//輸入第一個數爲空則不用入棧直接開始
if (map.top == 0)
{
map.stack[map.top] = i;
break ;
}
else
{
map.pop();
//判斷壓入之後是否正確;正確就直接壓一下個;不正確就清空
if (ShuDuUtil.IsRight(map.push(i)))
{
break;
}
else
{
map.pop();
map.push(10);
continue;
}
}
}
else
{
//判斷當前棧是否正確;
if (ShuDuUtil.IsRight(map.stack))
{
//如果正確,在壓入一個數。看看是否正確;正確就繼續往後壓;
if (ShuDuUtil.IsRight(map.push(i)))
{
break;
}
else
{
//如果不正確則+1繼續壓入;如果遍歷到9還未成功,則回溯;
if (i == 9)
{
map = ShuDuUtil.Back(out i, map);
}
else
{
map.pop();
}
continue;
}
}
//當前棧如果不正確,回溯。
else
{
if (map.top == 0)
{
map.stack[map.top] = i;
continue;
}
map.pop();
i = map.stack[map.top];
}
}
}
}
//將結果拼接成串 傳回去
StringBuilder resultStr = new StringBuilder();
foreach (int temp in map.stack)
{
resultStr = resultStr.Append(temp + ",");
}
return resultStr.ToString();
}
}
}
棧類:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
<pre name="code" class="csharp">using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ch.shudu.musoft.com.cn.Models
{
public class Map
{
//存數據的棧
public int[] stack{ get; set; }
//存儲標記該格子是否能被改變
public int[] tag { get; set; }
//棧指針
public int top;
//構造函數
public Map()
{
top = 0;
stack = new int[81];
tag = new int[81];
}
/// <summary>
/// 出棧
/// </summary>
public int[] pop() {
if (top != 0) {
if (tag[top] == 10)
{
stack[top] = 10;
top--;
}
else
{
top--;
pop();
}
}
return stack;
}
/// <summary>
/// 入棧
/// </summary>
/// <param name="i">存入的數</param>
/// <returns></returns>
public int[] push(int i)
{
//不能超過81
if (top < 81)
{
if (tag[top + 1] == 10)
{
top++;
stack[top] = i;
}
else
{
top++;
push(i);
}
}
return stack;
}
}
}
工具類:
using ch.shudu.musoft.com.cn.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ch.shudu.musoft.com.cn.Utils
{
public static class ShuDuUtil
{
/// <summary>
/// 數組轉爲棧
/// </summary>
/// <param name="jsonArray"></param>
/// <returns></returns>
public static Map toArray(Num[] numStack)
{
Map map = new Map();
for (int i = 0; i < numStack.Length; i++)
{
map.tag[i] = numStack[i].num;
map.stack[i] = numStack[i].num;
}
return map;
}
/// <summary>
/// 驗證當前數獨是否正確
/// </summary>
/// <param name="numStack"></param>
/// <returns></returns>
public static bool IsRight(int[] Stack)
{
//驗證每行是否正確
List<int> listInt = new List<int>();
for(int j = 0;j<9;j++){
for (int i = 0; i < 9; i++) {
if (Stack[i+j*9] != 10) {
listInt.Add(Stack[i + j* 9]);
}
}
if (!IsEquel(listInt))
{
return false;
}
listInt.Clear();
}
//驗證每列是否正確
for (int j = 0; j < 9; j++)
{
for (int i = 0; i < 9;i++ )
{
if (Stack[i * 9 + j] != 10)
{
listInt.Add(Stack[i*9+j]);
}
}
if (!IsEquel(listInt))
{
return false;
}
listInt.Clear();
}
//驗證每個框框內是否正確
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
for (int k = 0; k < 3; k++) {
if (Stack[i * 3 + j*9+k] != 10)
{
listInt.Add(Stack[i * 3 + j * 9 + k]);
}
}
}
if (!IsEquel(listInt))
{
return false;
}
listInt.Clear();
}
//驗證第二排
for (int i = 27; i < 34; i=i+3)
{
for (int j = 0; j < 3; j++)
{
for (int k = 0; k < 3; k++)
{
if (Stack[i + j * 9 + k] != 10)
{
listInt.Add(Stack[i + j * 9 + k]);
}
}
}
if (!IsEquel(listInt))
{
return false;
}
listInt.Clear();
}
//驗證第三排
for (int i = 54; i < 61; i = i + 3)
{
for (int j = 0; j < 3; j++)
{
for (int k = 0; k < 3; k++)
{
if (Stack[i + j * 9 + k] != 10)
{
listInt.Add(Stack[i + j * 9 + k]);
}
}
}
if (!IsEquel(listInt))
{
return false;
}
listInt.Clear();
}
return true;
}
/// <summary>
/// 判斷該數組集合類是否存在相同的數
/// </summary>
/// <param name="intArray"></param>
/// <returns></returns>
public static bool IsEquel(List<int> list) {
for(int i=0;i<list.Count;i++){
for(int j=0;j<list.Count;j++){
if(i != j && list[i]==list[j]){
return false;
}
}
}
return true;
}
/// <summary>
/// 回溯函數
/// </summary>
/// <param name="i"></param>
/// <param name="map"></param>
/// <returns></returns>
public static Map Back(out int i, Map map) {
if (map.tag[map.top] != 10)
{
map.top--;
i = map.stack[map.top];
map.pop();
}
else {
if (map.stack[map.top] == 9)
{
map.pop();
map = Back(out i, map);
}
else {
i = map.stack[map.top];
map.top--;
}
}
return map;
}
}
}