struct _Point{
int r;
int c;
bool operator < (const _Point & rht) const
{
if (r != rht.r) return r < rht.r;
return c < rht.c;
}
bool operator == (const _Point & rht) const
{
if (r == rht.r && c == rht.c) return true;
return false;
}
};
/****************************************************************************** * 函 数 名: X_Chain * A=B-C=D 和 D=C-B=A 重复的问题,目前的处理方式,会导致链重复。 * 功能描述: X-Chain方法 * 输 入: 无 * 输 出: 无 * 返 回 值: 无 * 作 者: WWW * 日 期: 2010年11月3日 * 版 本: V2.0 * 修改记录: * 日 期 版本 修改人 修改摘要 *****************************************************************************/ int Sudoku::X_Chain() { int r, i, j, k, nX; _Point pt; // list<_Point> lstPt; // list<_Point> links; // list<_Point>::iterator _iLstPt; // list<_Point>::iterator iLstLinks; bool bLeft = !true; // 向链的左侧延伸 list< list<_Point> > allLinks; multimap > candiLinks; for (r = 0; r < 9; ++r) { _CandiCnt_Map mapCandi; // 这里用作 候选数 与 位置信息对应表 GetLinks(HOUSE_ROW, r, true, 0, mapCandi); for (_CandiCnt_Map::iterator _itCandi=mapCandi.begin(); _itCandi!=mapCandi.end(); ++_itCandi) { nX = _itCandi->first; // 候选数 if(bLeft) pt = *--_itCandi->second.end(); else pt = *_itCandi->second.begin(); list< list<_Point> > lk; GetWeakStrongLinks(nX, _itCandi->second, !bLeft, lk); for (list< list<_Point> >::iterator ilk=lk.begin(); ilk!=lk.end(); ++ilk) { _Point p; if(bLeft) p = * ilk->begin(); else p = * --ilk->end(); _Point arrOut[15]; int num = GetInterSection(pt, p, 15, arrOut); k = 0; _Point arrDelPt[15]; for (i = 0; i < num; ++i) { ANSudokuCell &cTmp = m_anCell[arrOut[i].r][arrOut[i].c]; for (j = 0; j < cTmp.n; ++j) { if (cTmp.candi[j] == nX) { arrDelPt[k] = arrOut[i]; ++k; break; } } } //if (k <=0) continue; list<_Point> myLk = _itCandi->second; if (bLeft) { myLk.push_front(* ++ilk->begin()); myLk.push_front(* ilk->begin()); } else { myLk.push_back(* ilk->begin()); myLk.push_back(* ++ilk->begin()); } if( IsExist(candiLinks, myLk, nX)) continue; allLinks.push_back(myLk); // 有X-Chain printf("X-Chian:"); for (list<_Point>::const_iterator _iL=myLk.begin(); _iL!=myLk.end(); ++_iL) { printf("(%d,%d)", _iL->r, _iL->c); } printf(", 候选数%d 待删除位置", nX); for (i = 0; i < k; ++i) { printf("(%d,%d) ", arrDelPt[i].r, arrDelPt[i].c); } printf("/n"); } } } return 0 ; } /****************************************************************************** * 函 数 名: GetLinks(int house, int n, bool bStrong, int candi, _CandiCnt_Map & candiLinks) * 功能描述: 获取某row/col/box,候选数为candi的所有强或者弱链。这里认为强链 * 属于弱链。 * 输 入: hourse : row/ col/ box * n : 哪一行/col/box * bStrong : 强还是弱 * candi : 0 ,所有候选数, 1-9,特定候选数 * 输 出: 无 * 返 回 值: 无 * 作 者: WWW * 日 期: 2010年11月4日 * 版 本: V2.0 * 修改记录: * 日 期 版本 修改人 修改摘要 *****************************************************************************/ int Sudoku::GetLinks(int house, int n, bool bStrong, int candi, _CandiCnt_Map & candiLinks) { int i, k; int row[9]; int col[9]; _Point point; list<_Point> lstPt; _CandiCnt_Map::iterator _itCandi; if (house == HOUSE_BOX) { int r, c; i = 0; int _rowBegin = (n/3)*3; int _rowEnd = _rowBegin + 3; for (r = _rowBegin; r< _rowEnd; ++r) { int _colBegin = (n%3) * 3; int _colEnd = _colBegin + 3; for (c = _colBegin; c < _colEnd; ++c) { row[i] = r; col[i] = c; ++i; } } } else if (house == HOUSE_ROW) { for (i = 0; i < 9; ++i) { col[i] = i; row[i] = n; } } else if (house == HOUSE_COL) { for (i = 0; i < 9; ++i) { row[i] = i; col[i] = n; } } candiLinks.clear(); for (i = 0; i<9; ++i) { ANSudokuCell &cell = m_anCell[row[i]][col[i]]; for (k = 0; k < cell.n; ++k) { // 获取特定候选数的 链 Links if (candi > 0 && candi <=9 && candi != cell.candi[k]) continue; point.r = row[i]; point.c = col[i]; _itCandi = candiLinks.find(cell.candi[k]); if (_itCandi == candiLinks.end()) { lstPt.push_back(point); candiLinks.insert(_CandiCnt_Pair(cell.candi[k], lstPt)); lstPt.clear(); } else // 存在该候选数 { _itCandi->second.push_back(point); } } } for (_itCandi=candiLinks.begin(); _itCandi!=candiLinks.end(); /*++_itCandi*/) { list<_Point> _lp = _itCandi->second; // 强 链, 为2, 弱链大于2 if (bStrong && _itCandi->second.size() != 2) candiLinks.erase(_itCandi++); // box模式下,要求强链必须为斜线(直线情况下,已经被row或者col包含) else if(bStrong && house == HOUSE_BOX && _lp.size() == 2 && (_lp.begin()->r==(++_lp.begin())->r || _lp.begin()->c==(++_lp.begin())->c) ) candiLinks.erase(_itCandi++); else if (!bStrong && _itCandi->second.size() < 2) candiLinks.erase(_itCandi++); else ++_itCandi; } return 0; } /****************************************************************************** * 函 数 名: GetAllLinks(bool bStrong, int candi, _Point & head, _Point & tail, list<_Point> &links) * 功能描述: 获取链head-tail,以head为中间节点的所有弱或者强链。 * 输 入: head : 链的头 * tail : 链的尾 * 输 出: 无 * 返 回 值: 无 * 作 者: WWW * 日 期: 2010年11月4日 * 版 本: V2.0 * 修改记录: * 日 期 版本 修改人 修改摘要 *****************************************************************************/ int Sudoku::GetAllLinks(bool bStrong, int candi, _Point & head, _Point & tail, list<_Point> &links) { _CandiCnt_Map candiLinks; _CandiCnt_Map::iterator _itCandi; set<_Point> setLinks; list<_Point>::iterator _iLstPt; int num = 0; do { if (num == 0) GetLinks(HOUSE_ROW, head.r, bStrong, candi, candiLinks); else if (num == 1) GetLinks(HOUSE_COL, head.c, bStrong, candi, candiLinks); else if (num == 2) GetLinks(HOUSE_BOX, (head.r/3)*3 + head.c/3, bStrong, candi, candiLinks); for (_itCandi=candiLinks.begin(); _itCandi!=candiLinks.end(); ++_itCandi) { list<_Point> & lstP = _itCandi->second; for (_iLstPt = lstP.begin(); _iLstPt != lstP.end(); ++_iLstPt) setLinks.insert(*_iLstPt); } ++num; } while (num < 3); setLinks.erase(head); setLinks.erase(tail); links.clear(); for (set<_Point>::const_iterator iSetPt = setLinks.begin(); iSetPt!=setLinks.end(); ++iSetPt) links.push_back(*iSetPt); return 0; } /****************************************************************************** * 函 数 名: // * 功能描述: 获取链 In 以首(isHead=true)或者尾为起始点的弱强(-=)链。 * 要求 In 中 元素个数为 2,4,6,..., 即链为1,3,5,..., 奇数个链,此处 * 未作此校验,要求调用者保证。 * 输 入: nX : 候选数 * In : 起始链 * isHead : true, 以In的头节点为链首; false,以In的尾节点为链首 * 输 出: Out : 如果有弱强链,则通过Out输出所有这些链 * 返 回 值: true : 有弱强链; * false : 无弱强链 * 作 者: WWW * 日 期: 2010年11月8日 * 版 本: V2.0 * 修改记录: * 日 期 版本 修改人 修改摘要 *****************************************************************************/ bool Sudoku::GetWeakStrongLinks(int nX, list<_Point> & In, bool isHead, list< list<_Point> > & Out) { _Point p1, p2; // p1, 链首; p2, 连尾 if (isHead) { p1 = *-- --In.end(); p2 = *--In.end(); } else { p1 = *++In.begin(); p2 = *In.begin(); } Out.clear(); list<_Point> lstPt; list<_Point>::iterator _iLstPt; GetAllLinks(false, nX, p2, p1, lstPt); for (_iLstPt=lstPt.begin(); _iLstPt!=lstPt.end(); ++_iLstPt) { list<_Point> links; list<_Point>::iterator iLstLinks; GetAllLinks(true, nX, *_iLstPt, p2, links); for (iLstLinks=links.begin();iLstLinks!=links.end(); ++iLstLinks) { list<_Point> l; l.push_back(*_iLstPt); l.push_back(*iLstLinks); if (!isHead) l.reverse(); // 颠倒list的元素顺序 Out.push_back(l); } } return false; } // 强链 l 是否在强链容器 candiLinks 中存在 // 存在,返回false,不存在,返回true,并插入容器中。 bool IsExist(multimap >& candiLinks, list<_Point> & l, int nX) { typedef multimap >::iterator IT; list<_Point> lr = l; lr.reverse(); pair pii = candiLinks.equal_range(nX); for (IT it = pii.first; it != pii.second; ++it) { if (it->second.size() == l.size() && ( equal(l.begin(), l.end(), it->second.begin()) || equal(lr.begin(), lr.end(), it->second.begin()) ) ) return true; } candiLinks.insert(pair >(nX, l)); return false; }