/******************************************************************************
* 函 数 名: X_Chain
* A=B-C=D 和 D=C-B=A 重复的问题,目前的处理方式,会导致链重复。
* 功能描述: X-Chain方法
* 输 入: 无
* 输 出: 无
* 返 回 值: 无
* 作 者: WWW
* 日 期: 2010年11月3日
* 版 本: V2.0
* 修改记录:
* 日 期 版本 修改人 修改摘要
*****************************************************************************/
int Sudoku::X_Chain()
{
for (int r = 0; r < 18; ++r) // 9 row and 9 col
{
_CandiCnt_Map mapCandi; // 这里用作 候选数 与 位置信息对应表
if(r < 9)
GetLinks(HOUSE_ROW, r, true, 0, mapCandi);
else
GetLinks(HOUSE_COL, r-9, true, 0, mapCandi);
for (_CandiCnt_Map::iterator _itCandi=mapCandi.begin(); _itCandi!=mapCandi.end(); ++_itCandi)
{
int nX = _itCandi->first; // 候选数
list<list<_Point> > linksI; // 循环查找弱强链所用的容器
list<list<_Point> > linksN; // 向右侧查找弱强链所用的容器
bool bLeft = true; // 为true,则向链的左侧延伸
linksI.push_back(_itCandi->second);
while(!linksI.empty())
{
// 将I 中的第一个元素移到 N 中
linksN.splice(linksN.begin(), linksI, linksI.begin());
list<list<_Point> > lk;
GetWeakStrongLinks(nX, *linksN.begin(), !bLeft, lk);
for (list<list<_Point> >::iterator ilk=lk.begin(); ilk!=lk.end(); ++ilk)
{
if ( IsExist(*linksN.begin(), *ilk) ) continue;
_Point p; // 端点节点
list<_Point>::const_iterator cit;
if(bLeft) {
cit = ++linksN.begin()->begin();
p = * ilk->begin();
}
else {
cit = -- --linksN.begin()->end();
p = * --ilk->end();
}
_Point pt = *cit;
int nSize = linksN.begin()->size();
int nUsed = 2; // 一条链, 有两个点组成
int arrCandi[4];
arrCandi[0] = nX;
_Point arrDelPt[20];
int k = 0;
while(k <= 0) {
k = GetDelPos(pt, p, arrCandi, 1, arrDelPt);
if (nUsed+2 > nSize) break;
nUsed += 2;
if(bLeft) ++ ++cit;
else -- --cit;
pt = *cit;
}
//if (k <=0) continue;
list<_Point> links; // 测试后的链
if(bLeft) {
list<_Point>::const_iterator ci1 = linksN.begin()->begin();
copy(ci1, ++cit, inserter(links, links.begin()));
links.push_front(* ++ilk->begin());
links.push_front(* ilk->begin());
}
else {
list<_Point>::const_iterator ci1 = linksN.begin()->end();
copy(cit, ci1, inserter(links, links.begin()));
links.push_back(* ilk->begin());
links.push_back(* ++ilk->begin());
}
if (k <= 0) linksI.push_back(links);
// 有X-Chain
printf("X-Chian:");
for (list<_Point>::const_iterator _iL=links.begin(); _iL!=links.end(); ++_iL)
{
printf("(%d,%d)", _iL->r, _iL->c);
}
printf(", 候选数%d 待删除位置", nX);
for (int i = 0; i < k; ++i)
{
printf("(%d,%d) ", arrDelPt[i].r, arrDelPt[i].c);
}
printf("/n");
}
}
#if 1
// 向另一个方向查找链
bLeft = !bLeft;
while(!linksN.empty())
{
list<list<_Point> > lk;
GetWeakStrongLinks(nX, *linksN.begin(), !bLeft, lk);
for (list<list<_Point> >::iterator ilk=lk.begin(); ilk!=lk.end(); ++ilk)
{
if ( IsExist(*linksN.begin(), *ilk) ) continue;
_Point p; // 端点节点
list<_Point>::const_iterator cit;
if(bLeft) {
cit = ++linksN.begin()->begin();
p = * ilk->begin();
}
else {
cit = -- --linksN.begin()->end();
p = * --ilk->end();
}
_Point pt = *cit;
int nSize = linksN.begin()->size();
int nUsed = 2; // 一条链, 有两个点组成
int arrCandi[4];
arrCandi[0] = nX;
_Point arrDelPt[20];
int k = 0;
while(k <= 0) {
k = GetDelPos(pt, p, arrCandi, 1, arrDelPt);
if (nUsed+2 > nSize) break;
nUsed += 2;
if(bLeft) ++ ++cit;
else -- --cit;
pt = *cit;
}
//if (k <=0) continue;
list<_Point> links; // 测试后的链
if(bLeft) {
list<_Point>::const_iterator ci1 = linksN.begin()->begin();
copy(ci1, ++cit, inserter(links, links.begin()));
links.push_front(* ++ilk->begin());
links.push_front(* ilk->begin());
}
else {
list<_Point>::const_iterator ci1 = linksN.begin()->end();
copy(cit, ci1, inserter(links, links.begin()));
links.push_back(* ilk->begin());
links.push_back(* ++ilk->begin());
}
if (k <= 0) linksN.push_back(links);
// 有X-Chain
printf("X-Chian:");
for (list<_Point>::const_iterator _iL=links.begin(); _iL!=links.end(); ++_iL)
{
printf("(%d,%d)", _iL->r, _iL->c);
}
printf(", 候选数%d 待删除位置", nX);
for (int i = 0; i < k; ++i)
{
printf("(%d,%d) ", arrDelPt[i].r, arrDelPt[i].c);
}
printf("/n");
}
linksN.erase(linksN.begin());
}
#endif
}
}
return 0 ;
}
// p1 和 p2 可以共同看到的数格中,存在候选数 candi(个数为n)的数格通过 arrDel
// 输出。返回值为arrDel的元素个数
int Sudoku::GetDelPos(_Point& p1, _Point& p2, int candi[9], int n, _Point arrDel[20])
{
_Point arrOut[20];
int num = GetInterSection(p1, p2, 20, arrOut);
int k = 0;
for (int i = 0; i < num; ++i)
{
ANSudokuCell &cTmp = m_anCell[arrOut[i].r][arrOut[i].c];
for (int j = 0; j < cTmp.n; ++j)
{
for (int m = 0; m < n; ++m)
{
bool bValEqual = false;
if (cTmp.candi[j] == candi[m])
{
bValEqual = true;
arrDel[k] = arrOut[i];
++k;
break;
}
if (bValEqual) break;
}
}
}
return k;
}