xy-c

//----------------------------------
// [11/12/2010 anning]
// 獲取鏈 In 以首(isHead=true)或者尾爲起始點的弱強(-=)鏈。
void Sudoku::XY_ChainGetWeakStrongLinks(list<sdLink> & In, bool isHead, list<sdLink> & Out)
{
    _Point p1, p2;  // p1, 鏈首; p2, 鏈尾
    int nX;         // 候選數
    sdLink ln;

    list<sdLink>::const_iterator cit;
   
    if (isHead) {   //              (1,3)---> (3,Z)
        cit = --In.end();
        p1.r = cit->a/9;
        p1.c = cit->a%9;
        p2.r = cit->b/9;
        p2.c = cit->b%9;
        nX = cit->y;
        ln.x = nX;
    }
    else            //   (Z,1) <--- (1,3)
    {
        cit = In.begin();
        p1.r = cit->b/9;
        p1.c = cit->b%9;
        p2.r = cit->a/9;
        p2.c = cit->a%9;
        nX = cit->x;
        ln.y = nX;
    }

    Out.clear();
   

    list<_Point> lstPt;
    list<_Point>::iterator _iLstPt;
    GetAllLinks(false, nX, p2, p1, lstPt);
    for (_iLstPt=lstPt.begin(); _iLstPt!=lstPt.end(); ++_iLstPt)
    {
        ANSudokuCell & cell = m_anCell[_iLstPt->r][_iLstPt->c];
        if (cell.n != 2) continue;
       
        ln.a = ln.b = _iLstPt->r * SD_SIZE + _iLstPt->c;
        if (isHead)
            ln.y = cell.candi[0]==nX ? cell.candi[1] : cell.candi[0];
        else
            ln.x = cell.candi[0]==nX ? cell.candi[1] : cell.candi[0];

        Out.push_back(ln);
    }
}

// (1,2) (2,3) (3,4) (4,2) (2,1) 這裏只判斷和首節點的1有相同候選數的位置是否可消,
// 沒有判斷中間的滿足條件的數格,比如(2,3)(3,4)(4,2)鏈,有共同數字2。
// -----------------------------------------------------------------------------
// 這裏沒有過濾兩個節點組成的XY-Chain,因爲兩個節點組成的XY-Chain爲數對, 例如:
// (1,2)(2,1),由Naked Pair 方法消除。
bool Sudoku::XY_Chain()
{
    for (int i = 0; i < 81; ++i) // 81個數格(編號0-80)
    {
        ANSudokuCell & cell = m_anCell[i/9][i%9];
        if (cell.n != 2) continue;

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

        bool bLeft = true; // 爲true,則向鏈的左側延伸
        sdLink ln;
        ln.a = ln.b = i;
        ln.x = cell.candi[0];
        ln.y = cell.candi[1];
        list<sdLink> lk;
       
        lk.push_back(ln);
        linksI.push_back(lk);
        while(!linksI.empty())
        {
            // 將I 中的第一個元素移到 N 中
            linksN.splice(linksN.begin(), linksI, linksI.begin());

            list<sdLink>::const_iterator cit;
            _Point pt;
            int X;
            if(bLeft)  {
                cit = --linksN.begin()->end();
                pt.r = cit->b / 9;
                pt.c = cit->b % 9;
                X = cit->y;
            }
            else {
                cit = linksN.begin()->begin();
                pt.r = cit->a / 9;
                pt.c = cit->a % 9;
                X = cit->x;
            }
           
            XY_ChainGetWeakStrongLinks(*linksN.begin(), !bLeft, lk);
            for (list<sdLink>::iterator ilk=lk.begin(); ilk!=lk.end(); ++ilk)
            {
                if ( IsExist(*linksN.begin(), *ilk) ) continue;
               
                int arrCandi[1];
                _Point p; // 端點節點
             
                if(bLeft)  {
                    p.r = ilk->a / 9;
                    p.c = ilk->a % 9;
                    arrCandi[0] = ilk->x;
                }
                else {
                    p.r = ilk->b / 9;
                    p.c = ilk->b % 9;
                    arrCandi[0] = ilk->y;
                }

                list<sdLink> links  = *linksN.begin(); // 測試後的鏈
                if(bLeft)   links.push_front(*ilk);
                else        links.push_back(*ilk);

                int k = 0;
                _Point arrDelPt[20];
                if (arrCandi[0] == X)
                    k = GetDelPos(pt, p, arrCandi, 1, arrDelPt);
               
                if (k <= 0)  linksI.push_back(links);

                if (k <= 0) continue;

                printf("XY-Chian:");
                for (list<sdLink>::const_iterator _iL=links.begin(); _iL!=links.end(); ++_iL)
                {
                    printf("(%d,%d)", _iL->a / 9, _iL->a % 9);
                }
               
                printf(", Candi:%d Cells to del:", X);
               
                for (int i = 0; i < k; ++i)
                {
                    printf("(%d,%d) ", arrDelPt[i].r, arrDelPt[i].c);
                }
                printf("/n");
            }
        }

        // 向另一個方向查找鏈
        bLeft = !bLeft;
        while(!linksN.empty())
        {
            list<sdLink>::const_iterator cit;
            _Point pt;
            int X;
            if(bLeft)  {
                cit = --linksN.begin()->end();
                pt.r = cit->b / 9;
                pt.c = cit->b % 9;
                X = cit->y;
            }
            else {
                cit = linksN.begin()->begin();
                pt.r = cit->a / 9;
                pt.c = cit->a % 9;
                X = cit->x;
            }
           
            XY_ChainGetWeakStrongLinks(*linksN.begin(), !bLeft, lk);
            for (list<sdLink>::iterator ilk=lk.begin(); ilk!=lk.end(); ++ilk)
            {
                if ( IsExist(*linksN.begin(), *ilk) ) continue;
               
                int arrCandi[1];
                _Point p; // 端點節點
             
                if(bLeft)  {
                    p.r = ilk->a / 9;
                    p.c = ilk->a % 9;
                    arrCandi[0] = ilk->x;
                }
                else {
                    p.r = ilk->b / 9;
                    p.c = ilk->b % 9;
                    arrCandi[0] = ilk->y;
                }

                list<sdLink> links  = *linksN.begin(); // 測試後的鏈
                if(bLeft)   links.push_front(*ilk);
                else        links.push_back(*ilk);

                int k = 0;
                _Point arrDelPt[20];
                if (arrCandi[0] == X)
                    k = GetDelPos(pt, p, arrCandi, 1, arrDelPt);
               
                if (k <= 0)  linksN.push_back(links);

                if (k <= 0) continue;

                printf("XY-Chian:");
                for (list<sdLink>::const_iterator _iL=links.begin(); _iL!=links.end(); ++_iL)
                {
                    printf("(%d,%d)", _iL->a / 9, _iL->a % 9);
                }
               
                printf(", Candi:%d Cells to del:", X);
               
                for (int i = 0; i < k; ++i)
                {
                    printf("(%d,%d) ", arrDelPt[i].r, arrDelPt[i].c);
                }
                printf("/n");
            }
            linksN.erase(linksN.begin());
        }
    }

    return false;
}

// 鏈l是否包含鏈t
bool IsExist(list<sdLink> & l, sdLink & t)
{
    for (list<sdLink>::iterator ipt = l.begin(); ipt != l.end(); ++ipt)
        if (ipt->a==t.a && ipt->b==t.b || ipt->a==t.b && ipt->b==t.a) return true;

    return false;
}

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