查看: 2281|回復: 0
打印 上一主題 下一主題

[其他] HPCW2014 21 - SuDoKu

[複製鏈接]
  • TA的每日心情
    開心
    2015-4-12 10:09
  • 簽到天數: 137 天

    [LV.7]常住居民III

    142

    主題

    686

    帖子

    3559

    積分

    邁向天堂

    蘇多門

    Rank: 8Rank: 8

    積分
    3559

    新手達陣台南一中資訊社程式設計達人 - 2014

    跳轉到指定樓層
    樓主
    發表於 2014-4-20 17:24:41 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式

    趕快加入我們來參與討論吧!

    您需要 登錄 才可以下載或查看,沒有帳號?加入我們

    x
    本帖最後由 domen111 於 2015-1-30 11:37 編輯

    HP CodeWars 2014
    AC code(C#): http://ideone.com/uDQTZC

    題目概述:
    給你一個標準數獨的題目,請你算出答案。
    數獨規則: http://oddest.nc.hcc.edu.tw/wusu29.htm
    例如:
    ---26-7-1
    68--7--9-
    19---45--
    82-1---4-
    --46-29--
    -5---3-28
    --93---74
    -4--5--36
    7-3-18---


    解法:
    基本上遞迴下去暴力解就ok了。遞迴函式中測試1~9的數字是否可以填入,如果可以就繼續遞迴,直到解出題目,若不行就return回去上一遞迴。

    複雜度:
    如果隨便估計最壞的時間複雜度會是: 9^81 很恐怖的天文數字,不過事實上不可能到那麼大。
    以範例測資來說,Do被呼叫55次;空的題目是393次;我試過的幾題中最多的是11540次。

    心得:
    其實這個解數獨的程式是好幾年前就用C#寫好的視窗程式,寫了幾行輸出入就賺到17分(我們寫的其他題目大多5分左右),心得就是寫HP Code War時,記得要把以前寫過的code存在電腦裡,基本上hpcw就是一堆會寫的題目,時間內能寫多少就得幾分,如果有以前寫過的code就直接改一改輸出入丟上去,就省了很多時間,賺到好幾分,尤其像是這種較高分的題目。

    [C#] 純文本查看 復制代碼
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
     
    namespace prob21
    {
        class Program
        {
            static string[] SuDoKu = new string[81];
            static bool[] IsOriginal = new bool[81];  //是不是題目
     
            static void Main(string[] args)
            {
                string temp;
                for (int i = 0; i < 9; i++)
                {
                    temp = Console.ReadLine();
                    for (int j = 0; j < temp.Length; j++)
                    {
                        if (temp[j] == '-')
                            SuDoKu[i * 9 + j] = "";
                        else
                            SuDoKu[i * 9 + j] = temp[j].ToString();
                    }
                }
     
                for (int i = 0; i < 81; i++)
                {
                    if (SuDoKu[i].Trim() == "")
                        IsOriginal[i] = false;
                    else
                        IsOriginal[i] = true;
                }
     
                Do(0);
     
                for (int i = 0; i < 9; i++)
                {
                    for (int j = 0; j < 9; j++)
                    {
                        Console.Write(SuDoKu[i * 9 + j]);
                    }
                    Console.Write("\n");
                }
            }
     
                    //遞迴解題
            static bool Do(int i)
            {
                //檢查是不是題目
                while (i < 81 && IsOriginal[i])
                    i++;
                //檢查是不是已經解題了
                if (i > 80)
                    return true;
                //從1、2、3…9逐一測試直到成功
                for (int j = 1; j <= 9; j++)
                {
                    //檢查可不可以在這個地方填這個數字
                    if (Check(i, j.ToString()))
                    {
                        SuDoKu[i] = j.ToString();
                        //呼叫自己
                        if (Do(i + 1))  //如果傳回已經解題了,就回傳已經解題了
                            return true;
                        else          //如果傳回需要倒回去,就存空白的值
                            SuDoKu[i] = "";
                    }
                }
                return false;
            }
            static bool Check(int arrayNo, string data)
            {
                return CheckRow(arrayNo, data) && CheckColumn(arrayNo, data) && CheckGrid(arrayNo, data);
            }
            static bool CheckRow(int arrayNo, string data)
            {
                int rowNo = arrayNo / 9;
     
                for (int i = 0; i < 9; i++)
                {
                    if (SuDoKu[i + rowNo * 9] == data && (i + rowNo * 9) != arrayNo)
                    {
                        return false;
                    }
                }
                return true;
            }
            static bool CheckColumn(int arrayNo, string data)
            {
                int colNo = arrayNo % 9;
     
                for (int i = 0; i < 9; i++)
                {
                    if (SuDoKu[i * 9 + colNo] == data && (i * 9 + colNo) != arrayNo)
                    {
                        return false;
                    }
                }
                return true;
            }
            static bool CheckGrid(int arrayNo, string data)
            {
                int gridNo = arrayNo / 27 * 27 + arrayNo % 9 / 3 * 3;
     
                for (int i = 0; i < 3; i++)
                {
                    for (int j = 0; j < 3; j++)
                    {
                        if (SuDoKu[gridNo + i * 9 + j] == data && (gridNo + i * 9 + j) != arrayNo)
                        {
                            return false;
                        }
                    }
                }
                return true;
            }
        }
    }

    評分

    參與人數 1金幣 +3 收起 理由
    Sylveon + 3

    查看全部評分

    蘇多門 domen111
    My Web: https://sites.google.com/site/domenprg/
    回復

    使用道具 檢舉

    您需要登錄後才可以回帖 登入 | 加入我們

    本版積分規則

    快速回覆 返回頂部 返回列表