连连看 算法 2013-12-29

连连看算法:判断两个点是否能经过最多两次转折连通

连通情况有:

1.两点相邻

   直接返回true

2.两点不相邻

   进行横向搜索和纵向搜索

   a. 横向搜索

       求出两点分别从左右两边出发能到达的范围,然后再求出两个范围的交集

       如果没有交集,则返回false

       如果存在交集,则求交集中的维度是否存在一条直线连通,如图


       上面的A的范围为[1,5),下面的A的范围为[1,3),它们的交集为[1,3),只需判断(2,1)和(4,1), 或者(2,2)和(4,2)是否连通


       上面的A的范围为[4,5),下面的A的范围为[4,5),它们的交集为[4,5),只需判断(2,4)和(5,4)连通


    上面的A的范围为[5,7),下面的A的范围为[1,7),它们的交集为[5,7),只需判断(2,5)和(4,5), 或者(2,6)和(4,6)是否连通

   b. 纵向搜索 同理


   为了避免每次去判断两点是否连通,我使用了2个数组初始化后分别记录横向和纵向的空白直线

   struct line{

int begin;

        int end;

        line* pNext;

   }

   line* LineMap1[行数];

   line* LineMap2[列数];

   每次查询对应的行或列去找到相应的直线,只需判断该两点是否在这直线上即可,但每次删除点需要更新LineMap的值

   

   还有,像两个点在同一行的时候,只需纵向搜索

   相反,在同一列时,只需横向搜索.


   代码还不完整,不过基本实现了插入,删除,判断是否连接的函数了

   


#ifndef LMAP_H
#define LMAP_H

#define assert(a) ;
#include <iostream>
using namespace std;

typedef int vType;

struct lPoint{
	public:
		lPoint():m_bExist(false){}
		int m_nAbs;
		int m_nOrd;
		vType m_Value;
		bool m_bExist;
};

struct lLine{
	public:
		lLine():m_pNext(NULL){}
		lLine(int begin, int end):m_nBegin(begin),m_nEnd(end),m_pNext(NULL){}
		int m_nBegin;
		int m_nEnd;
		lLine* m_pNext;
};

const int MAX_ABS_DFL = 10;
const int MAX_ORD_DFL = 10;


class lMap{
	public:
		void Init(int max_abs = MAX_ABS_DFL, int max_ord = MAX_ORD_DFL);
		bool Insert(const int abs, const int ord, vType value);
		bool Erase(const int abs, const int ord);
		bool IsLinked(const int pointA_abs, const int pointA_ord, const int pointB_abs, const int pointB_ord);
		bool IsEmpty();
		bool IsDead();
		void PrintLineMap();
		void PrintMap();

	private:
		void _Insert(const int abs, const int ord, vType value);
		void _Erase(const int abs, const int ord);
		bool DoCheckLinked(const int pointA_abs, const int pointA_ord, const int pointB_abs, const int pointB_ord);
		bool IsLinkedInOneAbs(const int pointA_ord, const int pointB_ord, const int point_abs);
		bool IsLinkedInOneOrd(const int pointA_abs, const int pointB_abs, const int point_ord);
		bool IsLinkedInSomeAbs(const int pointA_ord, const int pointB_ord, const int point_abs_begin, const int point_abs_end);
		bool IsLinkedInSomeOrd(const int pointA_abs, const int pointB_abs, const int point_ord_begin, const int point_ord_end);
		bool _CheckLinkedInAbs(const int pointA_abs, const int pointA_ord, const int pointB_abs, const int pointB_ord);
		bool CheckLinkedInAbs(const int pointA_abs, const int pointA_ord, const int pointB_abs, const int pointB_ord);
		bool _CheckLinkedInOrd(const int pointA_abs, const int pointA_ord, const int pointB_abs, const int pointB_ord);
		bool CheckLinkedInOrd(const int pointA_abs, const int pointA_ord, const int pointB_abs, const int pointB_ord);
		void GetCommonRange(int rangeA_begin, int rangeA_end, int rangeB_begin, int rangeB_end, int& range_begin, int& range_end);


	private:
		lPoint* m_pMap;
		lLine** m_LineMap_abs;
		lLine** m_LineMap_ord;
		int m_nUsed;	
		int m_max_abs;
		int m_max_ord;
};

void lMap::PrintMap()
{
	cout << "map count:" << m_nUsed << endl;
	for(int i = 1; i < m_max_abs - 1; ++i)
	{
		for(int j = 1; j < m_max_ord - 1; ++j)
		{
			if(m_pMap[i * m_max_ord + j].m_bExist)
				cout << "| " << m_pMap[i * m_max_ord + j].m_Value << " ";
			else
				cout << "|   ";
			if(j == m_max_ord - 2)
				cout << "|";
		}
		cout << endl;
	}
}

void lMap::PrintLineMap()
{
	cout << "LineMap_abs:" << endl;
	for(int i = 0; i < m_max_abs; ++i)
	{
		cout << " < " << i << " > :";
		lLine* pLine = m_LineMap_abs[i];
		while(pLine != NULL)
		{
			cout << " (" << pLine->m_nBegin << ", " << pLine->m_nEnd << ") ";
			pLine = pLine->m_pNext;
		}
		cout << endl;
	}
	cout << endl << "LineMap_ord:" << endl;
	for(int i = 0; i < m_max_ord; ++i)
	{
		cout << " < " << i << " > :";
		lLine* pLine = m_LineMap_ord[i];
		while(pLine != NULL)
		{
			cout << " (" << pLine->m_nBegin << ", " << pLine->m_nEnd << ") ";
			pLine = pLine->m_pNext;
		}
		cout << endl;
	}
}

void lMap::Init(int max_abs, int max_ord)
{
	m_nUsed = 0;
	m_max_abs = max_abs + 2;
	m_max_ord = max_ord + 2;
	m_pMap = new lPoint[(m_max_abs) * (m_max_ord)];
	m_LineMap_abs = new lLine*[m_max_abs];
	for(int i = 0; i < m_max_abs; ++i)
		m_LineMap_abs[i] = new lLine(0, m_max_ord);
	m_LineMap_ord = new lLine*[m_max_ord];
	for(int i = 0; i < m_max_ord; ++i)
		m_LineMap_ord[i] = new lLine(0, m_max_abs);
}

bool lMap::IsEmpty()
{
	return m_nUsed == 0;
}

bool lMap::IsDead()
{
	return false;
}

bool lMap::IsLinked(const int pointA_abs, const int pointA_ord, const int pointB_abs, const int pointB_ord)
{
	if(!(m_pMap)[pointA_abs * m_max_ord + pointA_ord].m_bExist || !(m_pMap)[pointB_abs * m_max_ord + pointB_ord].m_bExist)
	{
		fprintf(stderr, "IsLinked: Point<%d, %d> or Point<%d, %d> not Exist!\n", pointA_abs, pointA_ord, pointB_abs, pointB_ord);
		return false;
	}
	if(pointA_abs == pointB_abs && pointA_ord == pointB_ord)
	{
		fprintf(stderr, "IsLinked: Point<%d, %d> and Point<%d, %d> are the same Point!\n", pointA_abs, pointA_ord, pointB_abs, pointB_ord);
		return false;
	}
	if((m_pMap)[pointA_abs * m_max_ord + pointA_ord].m_Value != (m_pMap)[pointB_abs * m_max_ord + pointB_ord].m_Value)
	{
		fprintf(stderr, "IsLinked: Point<%d, %d> and Point<%d, %d> are not the same Kind!\n", pointA_abs, pointA_ord, pointB_abs, pointB_ord);
		return false;
	}
	return DoCheckLinked(pointA_abs, pointA_ord, pointB_abs, pointB_ord);
}

bool lMap::Insert(const int abs, const int ord, vType value)
{
	if(m_pMap[abs * m_max_ord + ord].m_bExist)
	{
		fprintf(stderr, "Insert: Point<%d, %d> Exist!\n", abs, ord);
		return false;
	}
	_Insert(abs, ord, value);
	m_nUsed++;
	return true;
}

void lMap::_Insert(const int abs, const int ord, vType value)
{
	m_pMap[abs * m_max_ord + ord].m_Value = value;
	m_pMap[abs * m_max_ord + ord].m_bExist = true;
	lLine* pLine = m_LineMap_abs[abs];
	lLine* pTemp = pLine;
	while(pLine != NULL)
	{
		if(ord < pLine->m_nEnd)
		{
			if(pLine->m_nEnd - pLine->m_nBegin == 1)
			{
				pTemp->m_pNext = pLine->m_pNext;
				delete pLine;
			}
			else if(ord == pLine->m_nBegin)
				pLine->m_nBegin++;
			else if(ord == pLine->m_nEnd - 1)
				pLine->m_nEnd--;
			else
			{
				lLine* pNewLine = new lLine(ord + 1, pLine->m_nEnd);
				pLine->m_nEnd = ord;
				pNewLine->m_pNext = pLine->m_pNext;
				pLine->m_pNext = pNewLine;
			}
			break;
		}
		pTemp = pLine;
		pLine = pLine->m_pNext;
	}
	pLine = m_LineMap_ord[ord];
	pTemp = pLine;
	while(pLine != NULL)
	{
		if(abs < pLine->m_nEnd)
		{
			if(pLine->m_nEnd - pLine->m_nBegin == 1)
			{
				pTemp->m_pNext = pLine->m_pNext;
				delete pLine;
			}
			else if(abs == pLine->m_nBegin)
				pLine->m_nBegin++;
			else if(abs == pLine->m_nEnd - 1)
				pLine->m_nEnd--;
			else
			{
				lLine* pNewLine = new lLine(abs + 1, pLine->m_nEnd);
				pLine->m_nEnd = abs;
				pNewLine->m_pNext = pLine->m_pNext;
				pLine->m_pNext = pNewLine;
			}
			break;
		}
		pTemp = pLine;
		pLine = pLine->m_pNext;
	}
}

bool lMap::Erase(const int abs, const int ord)
{
	if(!(m_pMap)[abs * m_max_ord + ord].m_bExist)
	{
		fprintf(stderr, "Erase: Point<%d, %d> not Exist!\n", abs, ord);
		return false;
	}
	_Erase(abs, ord);
	m_nUsed--;
	return true;
}

void lMap::_Erase(const int abs, const int ord)
{
	m_pMap[abs * m_max_ord + ord].m_bExist = false;
	lLine* pLine = m_LineMap_abs[abs];
	lLine* pTemp = pLine;
	while(pLine != NULL)
	{
		if(ord < pLine->m_nBegin)
		{
			if(pLine->m_nBegin - pTemp->m_nEnd == 1)
			{
				pTemp->m_nEnd = pLine->m_nEnd;
				pTemp->m_pNext = pLine->m_pNext;
				delete pLine;
			}
			else if(ord == pLine->m_nBegin - 1)
				pLine->m_nBegin--;
			else if(ord == pTemp->m_nEnd)
				pTemp->m_nEnd++;
			else
			{
				lLine* pNewLine = new lLine(ord, ord + 1);
				pTemp->m_pNext = pNewLine;
				pNewLine->m_pNext = pLine;
			}
			break;
		}
		pTemp = pLine;
		pLine = pLine->m_pNext;
	}
	pLine = m_LineMap_ord[ord];
	pTemp = pLine;
	while(pLine)
	{
		if(abs < pLine->m_nBegin)
		{
			if(pLine->m_nBegin - pTemp->m_nEnd == 1)
			{
				pTemp->m_nEnd = pLine->m_nEnd;
				pTemp->m_pNext = pLine->m_pNext;
				delete pLine;
			}
			else if(abs == pLine->m_nBegin - 1)
				pLine->m_nBegin--;
			else if(abs == pTemp->m_nEnd)
				pTemp->m_nEnd++;
			else
			{
				lLine* pNewLine = new lLine(abs, abs + 1);
				pTemp->m_pNext = pNewLine;
				pNewLine->m_pNext = pLine;
			}
			break;
		}
		pTemp = pLine;
		pLine = pLine->m_pNext;
	}
}

bool lMap::DoCheckLinked(const int pointA_abs, const int pointA_ord, const int pointB_abs, const int pointB_ord)
{
	if(pointA_abs == pointB_abs)
	{
		if(pointB_ord - pointA_ord == 1 || pointA_ord - pointB_ord == 1)
			return true;
		else
			return CheckLinkedInOrd(pointA_abs, pointA_ord, pointB_abs, pointB_ord);
	}
	if(pointA_ord == pointB_ord)
	{
		if(pointA_abs - pointB_abs == 1 || pointB_abs - pointA_abs == 1)
			return true;
		else
			return CheckLinkedInAbs(pointA_abs, pointA_ord, pointB_abs, pointB_ord);
	}
	if(CheckLinkedInAbs(pointA_abs, pointA_ord, pointB_abs, pointB_ord))
		return true;
	else
		return CheckLinkedInOrd(pointA_abs, pointA_ord, pointB_abs, pointB_ord);
}

bool lMap::IsLinkedInOneAbs(const int pointA_ord, const int pointB_ord, const int point_abs)
{
	lLine* pLine = m_LineMap_abs[point_abs];
	while(pLine != NULL)
	{
		if(pLine->m_nEnd > pointA_ord)
		{
			if(pLine->m_nBegin <= pointA_ord && pLine->m_nEnd > pointB_ord)
				return true;
			else
				return false;
		}
		pLine = pLine->m_pNext;
	}
}

bool lMap::IsLinkedInOneOrd(const int pointA_abs, const int pointB_abs, const int point_ord)
{
	lLine* pLine = m_LineMap_abs[point_ord];
	while(pLine != NULL)
	{
		if(pLine->m_nEnd > pointA_abs)
		{
			if(pLine->m_nBegin <= pointA_abs && pLine->m_nEnd > pointB_abs)
				return true;
			else
				return false;
		}
		pLine = pLine->m_pNext;
	}
}

bool lMap::IsLinkedInSomeAbs(const int pointA_ord, const int pointB_ord, const int point_abs_begin, const int point_abs_end)
{
	for(int i = point_abs_begin; i < point_abs_end; ++i)
	{
		if(IsLinkedInOneAbs(pointA_ord, pointB_ord, i))
			return true;
	}
	return false;	
}

bool lMap::IsLinkedInSomeOrd(const int pointA_abs, const int pointB_abs, const int point_ord_begin, const int point_ord_end)
{
	for(int i = point_ord_begin; i < point_ord_end; ++i)
	{
		if(IsLinkedInOneOrd(pointA_abs, pointB_abs, i))
			return true;
	}
	return false;	
}

bool lMap::CheckLinkedInAbs(const int pointA_abs, const int pointA_ord, const int pointB_abs, const int pointB_ord)
{
	if(pointA_abs < pointB_abs)
		return _CheckLinkedInAbs(pointA_abs, pointA_ord, pointB_abs, pointB_ord);
	else
		return _CheckLinkedInAbs(pointB_abs, pointB_ord, pointA_abs, pointA_ord);
}

bool lMap::_CheckLinkedInAbs(const int pointA_abs, const int pointA_ord, const int pointB_abs, const int pointB_ord)
{
	int pointA_ord_begin = pointA_ord, pointA_ord_end = pointA_ord + 1;
	int	pointB_ord_begin = pointB_ord, pointB_ord_end = pointB_ord + 1;
	bool flag = false;
	lLine* pLine = m_LineMap_abs[pointA_abs];
	if(!m_pMap[pointA_abs * m_max_ord + pointA_ord - 1].m_bExist)
	{
		while(pLine != NULL)
		{
			if(pLine->m_nEnd == pointA_ord)
			{
				pointA_ord_begin = pLine->m_nBegin;
				flag = true;
				break;
			}
			pLine = pLine->m_pNext;
		}
		assert(pointA_ord_begin != pointA_ord);
	}
	if(!m_pMap[pointA_abs * m_max_ord + pointA_ord + 1].m_bExist)
	{
		if(flag)
		{
			pLine = pLine->m_pNext;
			assert(pLine != NULL && pointA_ord + 1 == pLine->m_nBegin);
			pointA_ord_end = pLine->m_nEnd;
			flag = false;
		}
		else
		{
			while(pLine != NULL)
			{
				if(pLine->m_nBegin == pointA_ord + 1){
					pointA_ord_end = pLine->m_nEnd;
					break;
				}
				pLine = pLine->m_pNext;
			}
			assert(pointA_ord_end != pointA_ord + 1);
		}
	}

	pLine = m_LineMap_abs[pointB_abs];
	if(!m_pMap[pointB_abs * m_max_ord + pointB_ord - 1].m_bExist)
	{
		while(pLine != NULL)
		{
			if(pLine->m_nEnd == pointB_ord)
			{
				pointB_ord_begin = pLine->m_nBegin;
				flag = true;
				break;
			}
			pLine = pLine->m_pNext;
		}
		assert(pointB_ord_begin != pointB_ord);
	}

	if(!m_pMap[pointB_abs * m_max_ord + pointB_ord + 1].m_bExist)
	{
		if(flag)
		{
			pLine = pLine->m_pNext;
			assert(pLine != NULL && pointB_ord + 1 == pLine->m_nBegin);
			pointB_ord_end = pLine->m_nEnd;
			flag = false;
		}
		else
		{
			while(pLine != NULL)
			{
				if(pLine->m_nBegin == pointB_ord + 1)
				{
					pointB_ord_end = pLine->m_nEnd;
					break;
				}
				pLine = pLine->m_pNext;
			}
			assert(pointB_ord_end != pointB_ord + 1);
		}
	}

	int point_ord_begin = 0, point_ord_end = 0;

	GetCommonRange(pointA_ord_begin, pointA_ord_end, pointB_ord_begin, pointB_ord_end, point_ord_begin, point_ord_end);

	if(point_ord_begin == point_ord_end)
		return false;

	return IsLinkedInSomeOrd(pointA_abs + 1, pointB_abs - 1, point_ord_begin , point_ord_end);
}

bool lMap::CheckLinkedInOrd(const int pointA_abs, const int pointA_ord, const int pointB_abs, const int pointB_ord)
{
	if(pointA_ord < pointB_ord)
		return _CheckLinkedInOrd(pointA_abs, pointA_ord, pointB_abs, pointB_ord);
	else
		return _CheckLinkedInOrd(pointB_abs, pointB_ord, pointA_abs, pointA_ord);
}

bool lMap::_CheckLinkedInOrd(const int pointA_abs, const int pointA_ord, const int pointB_abs, const int pointB_ord)
{
	int pointA_abs_begin = pointA_abs, pointA_abs_end = pointA_abs + 1;
	int	pointB_abs_begin = pointB_abs, pointB_abs_end = pointB_abs + 1;
	bool flag = false;
	lLine* pLine = m_LineMap_ord[pointA_ord];
	if(!m_pMap[(pointA_abs - 1) * m_max_ord + pointA_ord].m_bExist)
	{
		while(pLine != NULL)
		{
			if(pLine->m_nEnd == pointA_abs)
			{
				pointA_abs_begin = pLine->m_nBegin;
				flag = true;
				break;
			}
			pLine = pLine->m_pNext;
		}
		assert(pointA_abs_begin != pointA_abs);
	}
	if(!m_pMap[(pointA_abs + 1) * m_max_ord + pointA_ord].m_bExist)
	{
		if(flag)
		{
			pLine = pLine->m_pNext;
			assert(pLine != NULL && pointA_abs + 1 == pLine->m_nBegin);
			pointA_abs_end = pLine->m_nEnd;
			flag = false;
		}
		else
		{
			while(pLine != NULL)
			{
				if(pLine->m_nBegin == pointA_abs + 1){
					pointA_abs_end = pLine->m_nEnd;
					break;
				}
				pLine = pLine->m_pNext;
			}
			assert(pointA_abs_end != pointA_abs + 1);
		}
	}

	pLine = m_LineMap_ord[pointB_ord];
	if(!m_pMap[(pointB_abs - 1) * m_max_ord + pointB_ord].m_bExist)
	{
		while(pLine != NULL)
		{
			if(pLine->m_nEnd == pointB_abs)
			{
				pointB_abs_begin = pLine->m_nBegin;
				flag = true;
				break;
			}
			pLine = pLine->m_pNext;
		}
		assert(pointB_abs_begin != pointB_abs);
	}

	if(!m_pMap[(pointB_abs + 1) * m_max_ord + pointB_ord].m_bExist)
	{
		if(flag)
		{
			pLine = pLine->m_pNext;
			assert(pLine != NULL && pointB_abs + 1 == pLine->m_nBegin);
			pointB_abs_end = pLine->m_nEnd;
			flag = false;
		}
		else
		{
			while(pLine != NULL)
			{
				if(pLine->m_nBegin == pointB_abs + 1)
				{
					pointB_abs_end = pLine->m_nEnd;
					break;
				}
				pLine = pLine->m_pNext;
			}
			assert(pointB_abs_end != pointB_abs + 1);
		}
	}

	int point_abs_begin = 0, point_abs_end = 0;

	GetCommonRange(pointA_abs_begin, pointA_abs_end, pointB_abs_begin, pointB_abs_end, point_abs_begin, point_abs_end);

	if(point_abs_begin == point_abs_end)
		return false;

	return IsLinkedInSomeAbs(pointA_ord + 1, pointB_ord - 1, point_abs_begin , point_abs_end);
}

void lMap::GetCommonRange(int rangeA_begin, int rangeA_end, int rangeB_begin, int rangeB_end, int& range_begin, int& range_end)
{
	if(rangeA_begin < rangeB_begin)
	{
		if(rangeA_end <= rangeB_begin)
			return;
		else if(rangeB_end > rangeA_end)
		{
			range_begin = rangeB_begin;
			range_end = rangeA_end;
		}
		else
		{
			range_begin = rangeB_begin;
			range_end = rangeB_end;
		}
	}
	else
	{
		if(rangeB_end == rangeA_begin)
			return;
		else if(rangeB_end < rangeA_end)
		{
			range_begin = rangeA_begin;
			range_end = rangeB_end;
		}
		else
		{
			range_begin = rangeA_begin;
			range_end = rangeA_end;
		}
	}
}

#endif





  


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值