fc2

struct sdLink
{
    BYTE    a;  // a 點
    BYTE    b;  // b 點
    BYTE    x;  // a點的候選數x
    BYTE    y;  // b點的候選數y

    bool operator == (const sdLink & oth) const
    {
        return (a==oth.a && b==oth.b && x==oth.x && y==oth.y);
    }

    // 路徑相同
    bool equal (const sdLink & oth) const
    {
        return (a==oth.a && b==oth.b || a==oth.b && b==oth.a);
    }
};


// Forcing Chain 算法2 之數據結構
struct ANFcCell
{
    multimap<BYTE, sdLink> mapStrongLinks;
    multimap<BYTE, sdLink> mapWeakLinks;

    typedef multimap<BYTE, sdLink>  FCMap;
    typedef pair<BYTE, sdLink>      FCPair;
    typedef FCMap::iterator         FCIT;
    typedef pair<FCIT, FCIT>        FCII;

public:
    void AddStrongLink(const sdLink & l)
    {
        FCIT it;
        FCII ii = mapStrongLinks.equal_range(l.x);
        bool bExist = false;
        for (it = ii.first; it != ii.second; ++it)
        {
            if (l == it->second)
            {
                bExist = true;
                break;
            }
        }

        if (!bExist)
        {
            mapStrongLinks.insert(FCPair(l.x, l));
        }
    }

    void AddWeakLink(const sdLink & l)
    {
        FCIT it;
        FCII ii = mapWeakLinks.equal_range(l.x);
        bool bExist = false;
        for (it = ii.first; it != ii.second; ++it)
        {
            if (l == it->second)
            {
                bExist = true;
                break;
            }
        }

        if (!bExist)
        {
            mapWeakLinks.insert(FCPair(l.x, l));
        }
    }

    void OutPut(int i)
    {
        if (mapStrongLinks.empty() && mapWeakLinks.empty()) return;
       
        printf("No:%d, ", i);
        printf("Strong links num:%d; ", mapStrongLinks.size());
        printf("Weak links num:%d/n", mapWeakLinks.size());
        for (FCIT it=mapStrongLinks.begin(); it!=mapStrongLinks.end(); ++it)
        {
            sdLink & l = it->second;
            printf("key:%d, l.a:%d, l.b:%d, l.x:%d, l.y:%d/n", it->first, l.a, l.b, l.x, l.y);
        }
    }
};

bool Sudoku::ANForcingChain()
{
    ANFcCell fcell[81];
    sdLink link;

    _CandiCnt_Map candiLinks;
    _CandiCnt_Map::iterator _itCandi;
    list<_Point>::iterator _iLstPt;
    int i = 0;

    // 將每一行,每一列,每個九宮的強,弱鏈,存儲到 fcell中
    do {
        if (i < 9)
            GetLinks(HOUSE_ROW, i, false, 0, candiLinks);
        else if (i < 18)
            GetLinks(HOUSE_COL, i-9, false, 0, candiLinks);
        else
            GetLinks(HOUSE_BOX, i-18, false, 0, candiLinks);
       
        for (_itCandi=candiLinks.begin(); _itCandi!=candiLinks.end(); ++_itCandi)
        {
            link.x = link.y = _itCandi->first;
            list<_Point> & lstP = _itCandi->second;
            if (lstP.size() == 2) // 強鏈
            {
                link.a = lstP.begin()->SN();
                link.b = (++lstP.begin())->SN();
                fcell[link.a].AddStrongLink(link);
                fcell[link.a].AddWeakLink(link);

                swap(link.a, link.b);
                fcell[link.a].AddStrongLink(link);
                fcell[link.a].AddWeakLink(link);
                continue;
            }

            for (_iLstPt = lstP.begin(); _iLstPt != lstP.end(); ++_iLstPt)
            {
                list<_Point>::iterator iPt = _iLstPt;
                for (++iPt; iPt!=lstP.end(); ++iPt)
                {
                    link.a = _iLstPt->SN();
                    link.b = iPt->SN();
                    fcell[link.a].AddWeakLink(link);

                    swap(link.a, link.b);
                    fcell[link.a].AddWeakLink(link);
                }
            }
        }
        ++i;
    } while (i < 27);

    // 上述是針對單候選數(兩個數格)的情況,還要看不同候選數(單數格)的強弱鏈
    for (i = 0; i < 81; ++i)
    {
        ANSudokuCell &cell = m_anCell[i/9][i%9];
        if (cell.n == 0) continue;
       
        link.a = link.b = i;
        if (cell.n == 2) // 強鏈
        {
            link.x = cell.candi[0];
            link.y = cell.candi[1];
            fcell[link.a].AddStrongLink(link);
            fcell[link.a].AddWeakLink(link);
           
            swap(link.x, link.y);
            fcell[link.a].AddStrongLink(link);
            fcell[link.a].AddWeakLink(link);
            continue;
        }

        for (int p = 0; p < cell.n; ++p)
        {
            for(int q = p+1; q < cell.n; ++q)
            {
                link.x = cell.candi[p];
                link.y = cell.candi[q];
                fcell[link.a].AddWeakLink(link);
               
                swap(link.x, link.y);
                fcell[link.a].AddWeakLink(link);
            }
        }
    }


    // 打印輸出,驗證數據整理的是否正確
//     for (i = 0; i < 81; ++i)
//     {
//         fcell[i].OutPut(i);
//     }
//     printf("size=%d/n", sizeof(fcell));

    ANFcCell::FCIT it;
    ANFcCell::FCII ii;
    for (i = 0; i < 81; ++i)
    {
        ANSudokuCell &cell = m_anCell[i/9][i%9];
        if (cell.n == 0) continue;

        list<list<sdLink> > linksN;    // 循環查找弱強鏈所用的容器

        ii = fcell[i].mapStrongLinks.equal_range(m_solve[i/9][i%9]);
        for (it=ii.first; it!=ii.second; ++it)
        {
            list<sdLink> lk;
            lk.push_back(it->second);
            linksN.push_back(lk);
        }

        while(!linksN.empty())
        {
            //printf("linksN size=%d/n", linksN.size());

            sdLink & head = * linksN.begin()->begin();

            // 獲取弱鏈
            sdLink & tail = * --linksN.begin()->end();
            ii = fcell[tail.b].mapWeakLinks.equal_range(tail.y);
            for (it=ii.first; it!=ii.second; ++it)
            {
                link = it->second;
                if ( IsExist(*linksN.begin(), link) ) continue;
           
                // 獲取強鏈
                ANFcCell::FCII ii2 = fcell[link.b].mapStrongLinks.equal_range(link.y);
                for (ANFcCell::FCIT it2=ii2.first; it2!=ii2.second; ++it2)
                {
                    sdLink & tt = it2->second;
                    if (link.equal(tt) || IsExist(*linksN.begin(), tt) ) continue;

                    _Point arrDelPt[20];
                    int arrCandi[1];
                    int k = 0;

                    // 位置相同
                    if (head.a == tt.b)
                    {
                        if (head.x == tt.y) // 且候選數相等
                        {
                            arrCandi[0] = tt.y;
                            k = GetDelPos(_Point(head.a), _Point(tt.b), arrCandi, 1,

arrDelPt);
                        }
                    }
                    else
                    {
                        if (head.x == tt.y) // 且候選數相等
                        {
                            arrCandi[0] = tt.y;
                            k = GetDelPos(_Point(head.a), _Point(tt.b), arrCandi, 1,

arrDelPt);
                        }
                        else // 候選數不同
                        {
                            // same rule (row, col or box)
                            if (head.a/9 == tt.b/9 || head.a%9 == tt.b%9
                                || head.a/9*9+head.a%9 == tt.b/9*9+tt.b%9)
                            {
                                ANSudokuCell c2;
                                c2.n = 1;
                                c2.candi[0] = tt.y;
                               
                                if (IsInclude(m_anCell[head.a/9][head.a%9], c2))
                                {
                                    arrDelPt[k].r = head.a/9;
                                    arrDelPt[k].c = head.a%9;
                                    ++k;
                                }
                               
                                c2.candi[0] = head.x;
                                if (IsInclude(m_anCell[tt.b/9][tt.b%9], c2))
                                {
                                    arrDelPt[k].r = tt.b/9;
                                    arrDelPt[k].c = tt.b%9;
                                    ++k;
                                }
                            }
                        }
                    }

                    list<sdLink> links  = *linksN.begin(); // 測試後的鏈
                    links.push_back(link);
                    links.push_back(it2->second);

                    if (k <= 0)
                    {
                        linksN.push_back(links);
                        continue;
                    }

                   
                    printf("Forcing Chian:/n");
                    for (list<sdLink>::const_iterator _iL=links.begin(); _iL!=links.end();

++_iL)
                    {
                        printf("%d(%d,%d) (%d,%d)%d/n", _iL->x, _iL->a / 9, _iL->a % 9
                            , _iL->b / 9, _iL->b % 9, _iL->y);
                    }
                   
                    printf("Candi:%d Cells to del:", head.x);
                   
                    for (int j = 0; j < k; ++j)
                    {
                        printf("(%d,%d)", arrDelPt[j].r, arrDelPt[j].c);
                    }
                    printf("/n");
                    return true;
                }
            }
           
            linksN.erase(linksN.begin());
        }
    }

    return false;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章